setter fails/ gets passed by

3 次查看(过去 30 天)
Heinrich
Heinrich 2014-1-28
As the help file says:
Setter methods ( set.variable ) do not get called when assigning the target value inside this function as this could result in endless recursion.
Now I had the case, that I assig that very target value but it is from another instance of the class. But that is obscure. Cause it changes the value without doing the things that are nessesary leading to an inconsistent program state.
From my perspective this is a kind of bug or am I wrong?
classdef test < handle
properties
a
ref_To_Another_Instance_Of_This_Class
end
methods
function this = test( isSlave )
if nargin == 0 % prevent endless recursion
this.ref_To_Another_Instance_Of_This_Class = test( true );
this.a = 3;
end
end
function set.a( this , newA )
disp( 'setter method called' )
this.a = newA;
this.ref_To_Another_Instance_Of_This_Class.a = newA;
end
end
end

回答(2 个)

Jacob Halbrooks
Jacob Halbrooks 2014-1-29
I believe using the code below reproduces the unexpected behavior you write about, where a set on the top-level object does not propagate through all of the children:
>> t = test;
>> t.ref_To_Another_Instance_Of_This_Class = test;
>> t.a = 5;
>> t.ref_To_Another_Instance_Of_This_Class.a
ans =
5
>> t.ref_To_Another_Instance_Of_This_Class.ref_To_Another_Instance_Of_This_Class.a
ans =
3
This occurs because setting the child's "a" property in the set method of "a" bypasses the child's set method and just updates the property. I think this behavior makes sense with the understanding that the set function is defined on the class, and its requirement is that it not be re-entered.
In order to propagate the set all the way through the children, I would suggest the approach below, where "a" is made Dependent (you should get a Code Analyzer warning in your class advising this) and define a new method to perform the work of updating properties:
classdef test2 < handle
properties(Dependent)
a
end
properties
ref_To_Another_Instance_Of_This_Class
end
properties(Access=private)
pA;
end
methods
function this = test2( isSlave )
if nargin == 0 % prevent endless recursion
this.ref_To_Another_Instance_Of_This_Class = test2( true );
this.a = 3;
end
end
function set.a( this , newA )
disp( 'setter method called' )
this.updateA(newA);
end
function a = get.a(this)
a = this.pA;
end
function updateA(this, newA)
this.pA = newA;
if ~isempty(this.ref_To_Another_Instance_Of_This_Class)
this.ref_To_Another_Instance_Of_This_Class.updateA(newA);
end
end
end
end
This class can now be used to set "a" all the way through:
>> t2 = test2;
>> t2.ref_To_Another_Instance_Of_This_Class = test2;
>> t2.a = 5;
>> t2.ref_To_Another_Instance_Of_This_Class.a
ans =
5
>> t2.ref_To_Another_Instance_Of_This_Class.ref_To_Another_Instance_Of_This_Class.a
ans =
5

Heinrich
Heinrich 2014-1-29
编辑:Heinrich 2014-1-29
Hello Jacob Halbrooks,
" I think this behavior makes sense with the understanding that the set function is defined on the class, and its requirement is that it not be re-entered"
Thanks for your answer. I would disagree. The workaround you described is possible. I prefer just writing a "set_a( newA )" and apply it to the rest of the code BUT !:
In principle I think it is the result of an improper implementatation of the matlab object model. Of course a setter should not recurse . But it is another instance, it is another variable scope, the function would not recurse ! I think it should be improved as there are no disadvantages and it would be more consistent in the sence of real object orientation.
best regards

类别

Help CenterFile Exchange 中查找有关 Construct and Work with Object Arrays 的更多信息

Community Treasure Hunt

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

Start Hunting!

Translated by