Why is calling a superclass constructor after a use of the object not allowed?

17 views (last 30 days)
I have a subclass "subclass" of two classes "classA" and "classB", which are in turn subclasses of "superclass". Here is the class tree:
The superclass has two properties x and y. The classes "classA" and "classB" each do something special to initialize x and y, respectively. Then I want "subclass" to call both the "classA" and "classB" constructors to initialize x and y simultaneously. But the way the classes are built, I run into a snag.
Here are the definitions of the classes:
superclass.m:
classdef superclass
%% PROPERTIES
properties
x;
y;
end
%% METHODS
methods
function obj = superclass(x,y)
% Initialize the properties
obj.x = x;
obj.y = y;
end
end
end
classA.m:
classdef classA < superclass
%% PROPERTIES
properties
a;
end
%% METHODS
methods
% Constructor
function obj = classA(a,y,z)
x = a*z;
obj@superclass(x,y);
obj.a = a;
obj.z = z;
end
end
end
classB.m:
classdef classB < superclass
%% PROPERTIES
properties
b;
end
%% METHODS
methods
% Constructor
function obj = classB(x,b,z)
y = z+b;
obj@superclass(x,y);
obj.b = b;
obj.z = z;
end
end
end
subclass.m:
classdef subclass < classA & classB
%% METHODS
methods
% Constructor
function obj = subclass(a,b,z)
obj@classA(a,0,z);
obj@classB(obj.x,b,z); % Why is this not allowed and how do I work around that
% without redoing the calculations done in classes "classA" and "classB"?
end
end
end
This gives the following error message:
"A constructor call to superclass classB appears after the object is used, or after a return."
A couple of questions:
1) Why is calling a superclass constructor after a use of the object not allowed?
2) How do I work around that without redoing the calculations done in classA and classB? I feel like I might to redesign the class hierarchy. But it just bugs me that it can't be done like above.
I use Matlab R2019a on Windows 10.

Accepted Answer

Matt J
Matt J on 30 May 2019
Edited: Matt J on 30 May 2019
I can only speculate as to why it would not be allowed, but I assume there are hazards in using an object that is not finished being constructed...like feeding a baby that is only half way through being born, or driving a car that’s only half assembled.
Below is how I would re-implement. In your original design, it doesn't make sense to me that the classB constructor should have to set x if it has already been set in classA.
classdef superclass
%% PROPERTIES
properties
x;
y;
end
end
classdef classA < superclass
%% PROPERTIES
properties
a
end
properties (Access=private)
z
end
%% METHODS
methods
% Constructor
function obj = classA(a,z,y)
obj.x = a*z;
obj.a = a;
obj.z = z;
if nargin>2
obj.y=y;
end
end
end
end
classdef classB < superclass
%% PROPERTIES
properties
b
end
properties (Access=private)
z
end
%% METHODS
methods
% Constructor
function obj = classB(b,z,x)
obj.y = z+b;
obj.b = b;
obj.z = z;
if nargin>2
obj.x=x;
end
end
end
end
classdef subclass < classA & classB
%% METHODS
methods
% Constructor
function obj = subclass(a,b,z)
obj@classA(a,z); %set x but not y
obj@classB(b,z); %set y but not x
end
end
end

More Answers (2)

Matt J
Matt J on 31 May 2019
Edited: Matt J on 31 May 2019
Here's another variation, closer to your original design. The only substantive difference is that instead of subclass calling the constructors of classA and classB, it instead calls static methods from these classes.
classdef superclass
%% PROPERTIES
properties
x;
y;
z;
end
end
classdef classA < superclass
%% PROPERTIES
properties
a
end
%% METHODS
methods
% Constructor
function obj = classA(a,z,y)
if nargin
obj.x = ClassA.xcalc(a,z);
obj.a = a;
obj.z = z;
end
end
end
methods (Static)
function x=xcalc(a,z)
x=a*z;
end
end
end
classdef classB < superclass
%% PROPERTIES
properties
b
end
%% METHODS
methods
% Constructor
function obj = classB(b,z,x)
if nargin
obj.y = ClassB.ycalc(b,z);
obj.b = b;
obj.z = z;
end
end
end
methods (Static)
function y=ycalc(b,z)
y=z+b;
end
end
end
classdef subclass < classA & classB
%% METHODS
methods
% Constructor
function obj = subclass(a,b,z)
x=ClassA.xcalc(a,z);
y=ClassB.ycalc(b,z);
obj.x=x;
obj.y=y;
obj.a=a;
obj.b=b;
obj.z=z;
end
end
end

Matt J
Matt J on 31 May 2019
A 3rd variation, even closer to what you were doing originally. Here, we just shift everything the constructors were doing to ordinary class methods.
classdef superclass
properties
x;
y;
end
methods
function obj=setup(obj,x,y)
obj.x=x;
obj.y=y;
end
end
end
classdef classA < superclass
properties
a;
end
methods
% Constructor
function obj = classA(a,y,z)
if nargin
obj=obj.setup(a,y,z);
end
end
function obj=setup(obj,a,y,z)
obj=setup@superclass(obj,a*z,y);
obj.a = a;
end
end
end
classdef classB < superclass
%% PROPERTIES
properties
b;
end
%% METHODS
methods
% Constructor
function obj = classB(x,b,z)
if nargin
obj=obj.setup(obj,x,b,z);
end
end
function obj=setup(obj,x,b,z)
obj=setup@superclass(obj,x,b+z);
obj.b = b;
end
end
end
classdef subclass < classA & classB
%% METHODS
methods
% Constructor
function obj = subclass(a,b,z)
obj=obj.setup(a,b,z);
end
function obj=setup(obj,a,b,z)
obj=setup@classA(obj,a,0,z);
obj=setup@classB(obj, obj.x,b,z);
end
end
end

Categories

Find more on Class File Organization in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!