Modifying an immutable/protected variable of a subclass in a superclass method

11 vues (au cours des 30 derniers jours)
Hi,
I'm trying to modify an immutable/protected property of a sub class, using a superclass method or an external utility function (I'm trying to use this function in the subclass's constructor, of course).
Example (of what I would like to do):
classdef Sup
methods
function self = setProperties(self, varargin)
% This method sets the properties of the class
% the input arguments come in the form 'propname1', val1, 'propname2', val2, ...
...
end % setProperties
end % methods
end % classdef Sup
classdef sub < Sup
properties (SetAccess = immutable)
prop1
prop2
prop3
end % properties
methods
function self = sub(varargin)
% constructor
self = setProperties(self, varargin)
end % sup
end % methods
end % classdef sub
>> SomeObj = sub('prop1', 1, 'prop2', 10, 'prop3', 100);
This code doesn't work, I get the error message 'You cannot set the read-only property 'prop1' of sub.'
I'm OK with setting sub's properties to be protected, but I wouldn't want them to be public. I'm also OK with the idea that setProperties would be an external utility function (not defined in the superclass), but then again, I'm not able to use setProperties in the constructor of sub.
Would appreciate your help on that.
Thank you,
Avihay
  1 commentaire
per isakson
per isakson le 2 Mar 2015
Modifié(e) : per isakson le 2 Mar 2015
"modify an immutable [...] property" &nbsp Isn't the whole point that immutable properties cannot be modified?
No, I don't understand your question. What exactly do you want to do? Values can be assigned to the immutable properties in the constructor of sub. What would the point be using setProperties?

Connectez-vous pour commenter.

Réponse acceptée

Guillaume
Guillaume le 2 Mar 2015
You're trying to break the fundamental model of OOP: encapsulation. The whole concept of protected properties is that only the class (or its subclasses) can modify them. A superclass has no way to modify the properties of its subclasses. For that matter, there's no guarantee that a subclass would have the propery that it's trying to modify.
Secondly, why are you trying this indirect method for setting properties? Can't you just set the properties of the subclass the normal way? Or even just override your setProperties method in the subclass?
If you really want to set the properties from the superclass, what you can do though is have a method setsubProperties in the superclass that you then override in the subclass. You dispatch to this method from the setProperties method:
classdef Sup < handle %has to be a handle class to modify its own properties
methods
function setProperties(this, varargin)
this.setsubProperties(varargin);
end
end
methods (Access = protected)
function setsubProperties(this, varargin)
error('function must be overriden');
end
end
end
classdef sub < Sup
methods (Access = proteced)
function setsubProperties(this, varargin)
for varg = 1:2:numel(varargin)
%...
end
end
end
end

Plus de réponses (2)

Avihay
Avihay le 3 Mar 2015
Thank you very much, Guillaume, my initial idea was to make a superclass that would serve me with many different subclasses that I design. Since the setProperties operation should be the same for all of those subclasses, I thought that it would be nice if I could get rid of the verbosity of writing the same method for each and every one of these subclasses. Hence, I thought to put this method in the superclass (or an external utility function). At the same time, I would still like to have some protected (and even some immutable) properties in those subclasses.
Even though for my purposes this kine of method should be fine, as you mentioned, in the general case, this is probably a bad OOP practice.
Anyway, at the end, I did add these property setting lines to my subclasses' constructors; it's short enough. The idea of overriding the superclass' setProperties method in the subclass is nice, I would definitely consider it.
Thanks, again,
Avihay
  1 commentaire
Guillaume
Guillaume le 3 Mar 2015
If the properties are the same for all subclasses, then it should be part of the superclass interface.
If not, then the superclass should have no business messing with them since there's no guarantee that a particular subclass actually has the property.

Connectez-vous pour commenter.


Markus Leuthold
Markus Leuthold le 13 Mar 2015
While I agree that the initial code breaks encapsulation and is not best-practise, the code should still work in my opinion. The problem is that you cannot call functions out of the constructor which changes immutable properties.
classdef C < handle
properties(SetAccess=immutable)
x
end
methods
function obj=C
obj.fcn;
end
function fcn(obj)
obj.x=7;
end
end
end
Instantiating class C with
obj=C;
is not possible
You cannot set the read-only property 'x' of C.
When you call function f(), you're still in the scope of the constructor, therefore this should be allowed in my opinion. Immutability of x would still be guaranteed after the constructor is called
  2 commentaires
Guillaume
Guillaume le 13 Mar 2015
No, the code should not work. What the OP was trying to do is modify the property of a subclass from a superclass. That is given:
classdef base
method
function change_propderived
%???
end
end
end
classdef derived < base
properties
propderived
end
end
the OP was trying to modified propderived from a method of class base. That must be disallowed in any properly designed OOP language as you have no guarantee that an object of class base is actually an object of class derived. Consider:
classdef derived2 < base
properties
someotherprop
end
end
What should
d2 = derived2
d2.change_propderived
do?
Erik
Erik le 14 Mar 2016
Modifié(e) : Erik le 14 Mar 2016
Question: Why does the example given by Markus Leuthold result in an error?
He explains it very well in my opinion: ‘Immutability of x would still be guaranteed after the constructor is called’
Why can't the constructor call other functions or methods that might or might not modify the immutable properties? These functions would fail in all other non-constructor calls, because it is not the constructor calling them, but the constructor is allowed to set the properties, so why not call functions that set them?
An example of when this might be useful is a function that preprocesses or checks a property to be set, then sets it. The way it currently works, we can use a property checking method, but it may not set the immutable property. Instead, it should return the checked/preprocessed value, which in turn is to be used to set the property in the constructor.
I can imagine a problem with allowing the constructor calling a function that sets an immutable property: If the function called is changed somehow without you knowing, the constructor might construct a wrong object or result in an error. I don't see why this must be prevented like currently is the case, however, as you actually took responsibility for this the moment you called another function to set the property from within the constructor. Maybe you did this, because you actually have responsibility over the function being called (often another same-class or superclass method).
Could you illustrate a situation in which a call from the constructor to another class method (or any other function) that tries to set an immutable property becomes a problem?
Let me illustrate my point with the following example:
classdef C
properties (SetAccess = immutable)
p
end
methods (Static)
function obj = C
f(obj,1);
function f(obj,v)
obj.p = v;
end
end
end
end
Function f is locally defined within the constructor! Calling this local function fails, even though it resides within the constructor which guarantees the constructor setting the property.

Connectez-vous pour commenter.

Catégories

En savoir plus sur Subclass Definition dans Help Center et File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by