Inheritance, abstract and constant properties.
Show older comments
I am trying to write some classes that encapsulate concept definitions, but I'd also like to be able to define an alternate set of constant values for some of the properties.
At present, I have the following, and it works:
classdef my_supr (Abstract)
properties (Abstract, Constant)
foo;
baz;
end
end
classdef my_sub1 < my_supr
properties (Constant)
foo = 1;
baz = 2;
end
end
classdef my_sub2 < my_supr
properties (Constant)
foo = 7;
baz = 9;
end
end
Now this mostly works and my_sub1.foo returns 1, and my_sub2.foo returns 7. What I'd like to do is structure the hierarchy in a way that would let me define:
classdef my_sub3 < my_sub1
properties (Constant)
foo = 11; %This does not work
end
end
The intent here is to define the new set of constants, but only override some of them. Is there some magic combination of property attributes that would let me do this?
Accepted Answer
More Answers (3)
Steven Lord
on 4 Jun 2025
As a contrived example, let's say you had a Shape class that had an abstract and constant numSides property.
classdef Shape
properties(Abstract, Constant)
numSides
end
end
I could define a Square class that isa Shape with numSides equal to 4. This makes sense by the standard definition of a square shape:
classdef Square < Shape
properties(Constant)
numSides = 4;
end
end
Now if I were to define a Mysquare class that isa Square, an instance of Mysquare ought to be substitutable / usable anywhere I used an instance of Square. That's what the Liskov substitution principle says (very generally.)
classdef Mysquare < Square
properties(Constant)
numSides = 5;
end
end
A Square must have 4 sides.
A Mysquare must have 5 sides. [So we could have called this class the Pentagon class.]
So a Mysquare cannot be a Square.
But a Mysquare isa Square.
That's a contradiction.
For your real system of classes, how would you avoid this violation of Liskov?
1 Comment
Andrew Ouellette
on 4 Jun 2025
You can approximate this behavior with Dependent properties and getter methods.
classdef (Abstract) my_supr
properties (Dependent, SetAccess=private)
foo
end
methods
function foo = get.foo(this)
foo = this.getfoo();
end
end
methods (Abstract,Static,Access=protected)
foo = getfoo()
end
end
classdef my_sub1 < my_supr
methods (Static,Access=protected)
function foo = getfoo()
foo = 1;
end
end
end
classdef my_sub2 < my_supr
methods (Static,Access=protected)
function foo = getfoo()
foo = 7;
end
end
end
classdef my_sub3 < my_sub1
methods (Static,Access=protected)
function foo = getfoo()
foo = 11;
end
end
end
Something like this, perhaps?
classdef myclass
methods (Static)
function valid=approveProps(classname)
%props=eval("?"+classname); props=props.PropertyList;
props=matlab.metadata.Class.fromName(classname).PropertyList;
names={props.Name}; names=names([props.Constant] & ~[props.Hidden]);
valid=all(ismember(names,{'foo','bar','x','y','z'})); %approved list
if ~valid
disp("Illegal constant Property in class "+classname);
end
end
end
end
and then in the subclasses,
classdef mysubclass1<myclass
properties (Constant)
foo=1;bar=3; z=5;
end
properties (Constant, Hidden)
arePropsValid=myclass.approveProps(mfilename);
end
end
classdef mysubclass2<myclass
properties (Constant)
foo=1;
Q=1; %Unapproved property -- will throw error
end
properties (Constant, Hidden)
arePropsValid=myclass.approveProps(mfilename);
end
end
5 Comments
Paul
on 4 Jun 2025
Hi Matt,
Would there be a way to change approveProps to accept the instance of mysubclass as the input and then call metaclass, ? on that (instead of using eval)? I'm not suggesting that your approach is bad, just trying learn about OOP in Matlab.
Steven Lord
on 4 Jun 2025
Use the matlab.metadata.Class.fromName function instead of eval with the ? operator. [Note that this was moved from one namespace to another in release R2024a, as shown in the Version History section on that documentation page.] Or if you have an instance of the class, calling metaclass on that instance is sufficient.
Matt J
on 4 Jun 2025
@Steven Lord That's good to know about, but I wonder why not just extend metaclass, ? to allow the syntax
metaclass(classname)
Is there anything inherently problematic with using eval here?
"if you have an instance of the class"
Does the properties block not have the instance of the class on which the properties are being set? Or is that not the case because the instance isn't fully constructed (so to speak) yet? In either case, the "if you have" is throwing me off. It sounds like there might be some uses where the class instance is available and other uses where it's not.
If metaclass(classname) were allowed then
metaclass("myobject")
would be ambiguous. Should that return the Class of the myobject class, or the Class of the string class, of which "myobject" is an instance, as it does currently.
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!