MATLAB: Storing classes as appdata and modifying them

appdataclassgetappdataobjectoopsetappdata

Apologies if this has been asked before, I have not been able to find any similar questions on Matlab Central or any other site.
Say I have a variable, and I store this variable as AppData. If I go modify the variable after storing it as appdata, it will not change the appdata.
>> number = 0;
>> setappdata(0,'NumberStorage',number)
>> number = 10;
>> getappdata(0,'NumberStorage')
ans =
0
Say I have a class, defined as follows:
classdef SampleClass < dynamicprops
properties
testValue = 0;
end
end
If I create an instance of this class and store it as appdata and then modify it after the fact, it does change the appdata.
>> object = SampleClass;
>> object.testValue = 0;
>> setappdata(0,'ObjectStorage',object)
>> object.testValue = 10;
>> getappdata(0,'ObjectStorage')
ans =
SampleClass with properties:
testValue: 10
My question is, why does this happen? And how can I prevent it from happening?

Best Answer

This behaviour probably has to do with the fact that the SampleClass is derived from dynamicprops which is itself derived from the class handle (see http://www.mathworks.com/help/matlab/ref/dynamicprops.html)
classdef myclass < dynamicprops makes myclass a subclass of the dynamicprops class, which is a subclass of the handle class
From the documentation for the handle class (see http://www.mathworks.com/help/matlab/ref/handle.html)
The handle class is the superclass for all classes that follow handle semantics. A handle is a reference to an object. If you copy an object's handle, MATLAB® copies only the handle and both the original and copy refer to the same object data. If a function modifies a handle object passed as an input argument, the modification affects the original input object.
So when the code calls
setappdata(0,'ObjectStorage',object)
it is setting/copying the handle (reference) to the object and not the object itself. So any change to the original object affects that saved through the setappdata function as well.
Is there a particular reason why the SampleClass is derived from dynamicprops and is not just simply a Value (non-handle) class? If the latter (defined as just classdef SampleClass) then a copy of the object would be made when calling the setappdata.
Not deriving from handle is one alternative to solving the problem. Another is to just create another instance of this object and copy over the data. You could create a copy constructor for SampleClass that would copy each member from the source to the destination. For example (renaming to SampleClass2),
classdef SampleClass2 < dynamicprops
properties
testValue = 0;
end
methods
function [x] = SampleClass2(varargin)
x.testValue = 0;
if nargin==1
inp = varargin{1};
if strcmpi(class(inp),'SampleClass2')
x.testValue = inp.testValue;
else
% do something else
end
end
end
end
end
In the above constructor, we check to see how many inputs there. If there is just the one and its class type is SampleClass2 then we copy over the contents from the source to the destination.
Now try your above example as
object = SampleClass2;
object.testValue = 0;
setappdata(0,'ObjectStorage',SampleClass2(object))
object.testValue = 10;
getappdata(0,'ObjectStorage')
ans =
SampleClass2 with properties:
testValue: 0
Hope that this helps!