问题
In MatLab, i have a superclass A that takes some parameters, x and y
classdef A < handle
properties
x;
y;
z;
end
methods
function this = A(x, y)
this.x = x;
this.y = y;
this.initialize();
end
function initialize(this)
this.z = this.x + this.y;
end
end
end
The initialize method is supposed to do some initial calculations to fasten computation later.
Now i want to create a child class B of A, with it's own inialization, but B should be initialized before A.
classdef B < A
properties
p
end
methods
% B takes another parameter p
function this = B(p)
% Since B is a subclass of A, and A takes some parameters we have to
% call the constructer of A as the first thing.
this = this@A([], []);
this.p = p;
end
function initialize(this)
this.x = this.p(1);
this.y = this.p(2);
% This is when initialize of A should be called.
end
end
end
Basically i just want to initialize B before A, but because the constructer of the parent have to be called as the first thing, i cannot figure out how to do this.
In PHP I would do something like this
class A {
public function __construct($x, $y) {
$this->x = $x;
$this->y = $y;
$this->initialize();
}
public function initialize() {
$this->z = $this->x + $this->y;
}
}
class B extends A {
public function __construct($p) {
// Does not call the parent constructor.
$this->p = $p;
$this->initialize();
}
public function initialize() {
$this->x = $this->p[0];
$this->y = $this->p[1];
parent::initialize(); // Now we are ready to initialize A
}
}
Is there a smart way to design what i want in MatLab? Do i have to give up the inheritance of A in class B?
回答1:
The complication arises since:
If you create a subclass object, MATLAB® calls the superclass constructor to initialize the superclass part of the subclass object. By default, MATLAB calls the superclass constructor without arguments. [src]
You can get around explicitly calling the superclass constructor by wrapping its work in an if
-statement dependent on how many arguments it was passed (nargin):
function this = A(x, y)
if (nargin ~= 0) % or (nargin == 2) in this case
this.x = x;
this.y = y;
this.initialize();
end
end
And then B
's methods would look like:
function this = B(p)
this.p = p;
this.initialize();
end
function initialize(this)
this.x = this.p(1);
this.y = this.p(2);
initialize@A(this);
end
It may just be error in the post, but A
's initialize
method is referencing undefined variables x
and y
and not their properties. It should be:
function initialize(this)
this.z = this.x + this.y;
end
回答2:
This goes against the principles of OOP. What you are trying to achieve basically rules out that B
should be derived from A
. From what I can tell, you really want to overload the constructor of A
. Either do this using a nargin
check in A
, or if you really want to have a B
for whatever reason, just use: this = this@A(p(1), p(2);
in the constructor of B
instead, to properly call the constructor of A
(and get rid of the property p
).
This is how you would simulate to overload the constructor by using nargin
:
classdef A < handle
properties
x;
y;
z;
end
methods
function this = A(x, y)
if nargin==1 % 'p' was passed as 'x'
this.x = x(1);
this.y = x(2);
else
this.x = x;
this.y = y;
end
this.initialize();
end
function initialize(this)
this.z = this.x + this.y;
end
end
end
This is how you would derive B
from A
, with a proper call of A
's constructor:
classdef B < A
methods
function this = B(p)
this = this@A(p(1), p(2));
end
end
end
来源:https://stackoverflow.com/questions/28626730/initialize-child-before-parent-do-not-call-parent-contructor