GreasyChicken
GreasyChicken

Reputation: 11

Concrete Matlab class with abstract property member class, is this possible?

New to Matlab but forced to use it for a new work project... I'm coming from a C++ background, but maybe I should not try to emulate coding paradigms from C++ with Matlab. I'm trying to figure out how to have a abstract class property that gets initialized when the constructor is called with a concrete member. For instance:

%AbstractClass.m
classdef (Abstract) AbstractClass < handle
end
%ConcreteClass.m
classdef ConcreteClass < AbstractClass
end
%myclass.m
classdef myclass < handle
    properties
        % X {AbstractClass}  % would like to have this be like C++ nullptr 
        %X {AbstractClass} % can't initialize...
        %X % Works, but not safe 
        X {mustBeA(X, 'AbstractClass')} % Suggested, error below    
    end

    methods
        % constructor 
        function obj = myclass( concreteInstanceOfAbstractClass )
            obj.X = concreteInstanceOfAbstractClass 
        end
    end
end

But when I try to run this

Y = ConcreteClass()
mustBeA(AbstractClass, Y) % no error, fine 
mustBeA(ConcreteClass, Y) % no error, fine 
A = myclass(Y)            % throws error below

I get the following error

>> A = myclass(Y)
Error using implicit default value of property 'X' of class 'myclass'. Value must be one of the following types: 'AbstractClass'.

Is there a way to initialize the class in the constructor using the concrete instance of Abstract class? I have done some searching, but I'm new enough to Matlab that I'm probably not looking in the right places. This would be a very common thing to do in C++.

Upvotes: 1

Views: 360

Answers (1)

Edric
Edric

Reputation: 25140

Try

properties
    X {mustBeA(X, 'AbstractClass')}
end

which is a property validator rather than a class constraint.

Further to comments below, I realise the problem is that MATLAB insists on having a default value in the classdef. Unfortunately, this makes things difficult. One approach is to supply a valid concrete class as the default value. This works:

properties
    X AbstractClass = ConcreteClass
end

but requires that the using class knows the name of ConcreteClass. Another approach (especially if the property needs to be set only at construction time) is this:

classdef Uses
    properties (SetAccess = immutable)
        % No constraints here
        Property
    end
    
    methods
        function obj = Uses(val)
            arguments
                % Enforce constraints here - scalar instance
                % of something inheriting from AbstractClass
                val (1,1) AbstractClass
            end
            obj.Property = val;
        end
    end
end

Upvotes: 1

Related Questions