Inheritance, abstract and constant properties.
4 views (last 30 days)
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?
0 Comments
Accepted Answer
Benjamin Kraus
on 4 Jun 2025
Edited: Benjamin Kraus
on 4 Jun 2025
Based on this statement:
What I really want is:
#define foo (1)
#if MY_SW_VERSION > 1
#define baz(2)
#else
#define baz(1)
#endif
I think what you are really looking for is a singleton pattern.
There are several mechanisms for implementing a singleton in MATLAB, but here's my favorite somewhat unintuitive method.
classdef Registry < handle
properties (Constant)
% When the "Registry" object is first initialized, it populates the
% ConstantsRegistry object with an object. Because
% ConstantsRegistry is a handle-class object, that same object is
% shared by all instances of "Registry".
ConstantsRegistry (1,1) ConstantsRegistry = ConstantsRegistry
end
end
classdef ConstantsRegistry < handle
properties
Constants
end
end
classdef Constants
properties (Constant)
Foo = 1;
end
end
classdef AlternateConstants
properties (Constant)
Foo = 2;
end
end
Registry.ConstantsRegistry.Constants.Foo % Returns 1
Registry.ConstantsRegistry.Constants = AlternateConstants;
Registry.ConstantsRegistry.Constants.Foo % Returns 2
Alternatively
A much more common and intuitive version of a singleton in MATLAB:
classdef Registry < handle
properties
Constants
end
methods (Access=private)
% Restrict access to the constructor so that only one object can be
% constructed.
function obj = Registry()
obj.Constants = Constants;
end
end
methods (Static)
function obj = getInstance()
persistent instance
if isempty(instance) || ~isvalid(instance)
instance = Registry();
end
obj = instance;
end
end
end
classdef Constants
properties (Constant)
Foo = 1;
end
end
classdef AlternateConstants
properties (Constant)
Foo = 2;
end
end
Registry.getInstance().Constants.Foo % Returns 1
r = Registry.getInstance();
r.Constants = AlternateConstants;
Registry.getInstance().Constants.Foo % Returns 2
0 Comments
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?
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
Matt J
on 4 Jun 2025
Edited: Matt J
on 4 Jun 2025
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
Edited: Paul
on 4 Jun 2025
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.
See Also
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!