Reputation: 23
I have a MATLAB class called super:
classdef super < handle
properties
aString = '';
end
methods
function obj = super(obj, value)
obj.aString = value;
end
function set.aString(obj, value)
obj.aString = value;
end
end
end
I want to override the set function in a subclass derived from 'super':
classdef sub < super
%// Property 'aString' is inherited from super
methods
function obj = sub(obj, value)
%// Must include call to super constructor otherwise MATLAB will by
%// default call constructor with no arguments but my super class
%// requires one argument in constructor. This call should probably
%// super set method. But I don't care.
obj = obj@super('');
%// Now that super constructor has returned, call sub overriding
%// set method
obj.aString = value;
end
function set.aString(obj, value)
obj.aString = value;
end
end
end
The code above gives me the following error:
> Cannot define property 'aString' in class 'sub' because the property
> has already been defined in the superclass 'super'
Adding the property definition to 'sub' results in the same error.
I have also unsuccessfully tried using "Abstract" as a workaround, where I define an Abstract class:
classdef (Abstract) bloat < handle
properties (Abstract)
aString
end
end
and then try implementing 'super' as a child of 'bloat':
classdef super < bloat
%// Remainder of super code remains the same
Which did not work as I guess by the time 'sub' inherites, 'aString' is "concrete". I then, in addition to the above modification, tried modifying 'sub' to include 'boat' in its class definition:
classdef sub < super & bloat
%// Remainder of super code remains the same
This also did not work.
I have been unable to find any MATLAB documentation that specifically says: "You cannot modify set and get methods".
I'm hoping that my syntax is simply incorrect, but from searching I now fear that MATLAB does not allow this (either as a bug or by design).
EDIT: I am using MATLAB 2013a
Thank you
Upvotes: 2
Views: 5421
Reputation: 2409
First, since the question includes request for a reference to the Matlab documentation:
The Matlab documentation on Property Access Methods states (currently for rev. 2015a):
You can define property access methods only:
- For concrete properties (that is, properties that are not abstract)
- Within the class that defines the property (unless the property is abstract in that class, in which case the concrete subclass must define the access method).
So it seems overriding get/set-methods is not possible by design.
Second, here is another quirky workaround: One can make a property observable and in the event notifier change the value. So in the super class we set the SetObservable flag:
super.m:
classdef super < handle
properties (SetObservable)
aString;
end
methods
function obj = super(value)
obj.aString = value;
end
function set.aString(obj, value)
obj.aString = value;
end
end
end
And in the sub class a listener is introduced in the constructor. It points to a function which is called whenever the property value is assigned. The function then checks the value (and corrects/changes it when necessary).
sub.m:
classdef sub < super
%// Property 'aString' is inherited from super
methods
function obj = sub(value)
%// Must include call to super constructor otherwise MATLAB will by
%// default call constructor with no arguments but my super class
%// requires one argument in constructor. This call should probably
%// super set method. But I don't care.
obj = obj@super('');
%// Now that super constructor has returned, call sub overriding
%// set method
obj.aString = value;
addlistener(obj, 'aString', 'PostSet',@obj.checkAString);
end
function checkAString(self, ~, ~)
if isempty(self.aString)
self.aString = 'was empty';
end;
end
end
end
if you then run
a_sub = sub('');
a_sub.aString = ''
You'll get:
a_sub =
sub with properties:
aString: 'was empty'
as a result.
However, this is not an ideal solution either. There are at least these drawbacks:
Upvotes: 2
Reputation: 124573
Another solution is to make the set method call a protected function to perform whatever logic you need on assignment. This protected method can of course be overriden in subclasses.
Although unrelated to the issue above, it is always preferable to have a constructor that accepts zero arguments as well your current constructor. See the changes I made in that regard.
classdef super < handle
properties
x = 1; % some property with a default value
end
methods
function obj = super(value)
% allow for zero-argument construction
if nargin > 0
obj.x = value;
end
end
function set.x(obj, value)
% call another function to check the value as desired,
% and possibly even update it using some computation
value = checkX(obj, value);
% set set the property using the validated value
% (only place we do assignment to avoid infinite recursion)
obj.x = value;
end
end
methods (Access = protected)
function value = checkX(obj, value)
% for example, we require that values be scalar positive
validateattributes(value, {'numeric'}, {'scalar','positive'});
end
end
end
classdef sub < super
methods
function obj = sub(value)
% set inherited property if requested
if nargin > 0
obj.x = value;
end
end
end
methods (Access = protected)
function value = checkX(obj, value)
% we could call superclass method to combine effect
value = checkX@super(obj, value);
% or override super-class logic (example: maximum value of 10)
value = min(value,10);
end
end
end
Upvotes: 4
Reputation: 74940
You will have to have your set method call a different method which you then can overload. This requires you to make aString
dependent, and store its value somewhere else to avoid infinite recursions.
classdef super < handle
properties (Dependent)
aString
end
properties (Hidden)
storeAString = '';
end
methods
function obj = super(obj, value)
obj.aString = value;
end
function set.aString(obj, value)
setString(obj,value);
end
function value = get.aString(obj)
value = obj.storeAString;
end
end
methods (Hidden)
function setString(obj,value)
%# this is the method you will be able to overload
obj.storeAString = value;
end
end
end
Upvotes: 2