Modifying an immutable/protected variable of a subclass in a superclass method
18 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
Avihay
el 2 de Mzo. de 2015
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 comentario
per isakson
el 2 de Mzo. de 2015
Editada: per isakson
el 2 de Mzo. de 2015
"modify an immutable [...] property"   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?
Respuesta aceptada
Guillaume
el 2 de Mzo. de 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
0 comentarios
Más respuestas (2)
Avihay
el 3 de Mzo. de 2015
1 comentario
Guillaume
el 3 de Mzo. de 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.
Markus Leuthold
el 13 de Mzo. de 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 comentarios
Guillaume
el 13 de Mzo. de 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
el 14 de Mzo. de 2016
Editada: Erik
el 14 de Mzo. de 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.
Ver también
Categorías
Más información sobre Subclass Applications en Help Center y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!