Why is calling a superclass constructor after a use of the object not allowed?
    8 views (last 30 days)
  
       Show older comments
    
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.
0 Comments
Accepted Answer
  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
0 Comments
More Answers (2)
  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
0 Comments
  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
0 Comments
See Also
Categories
				Find more on Subclass Definition 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!
