MATLAB: How to change the class definition without changing the behavior of old objects (e.g. those saved in a MAT-file)

designMATLABoop

I want to update the definition of my class with new behavior in a non backward compatible way, but I still want to be able to use old instances of the class and have them use the old class definition (i.e. with the old behavior).
Suppose I have a class named MyClass (defined as follows) and I have some instances of MyClass saved to a MAT-file.
% MyClass.m

classdef MyClass < handle
properties
value (1,1) double
end
methods
function obj = MyClass()
obj.value = 0;
end
function v = getValue(obj)
v = obj.value;
end
function v = add(obj,a,b)
v = a + b;
obj.value = v;
end
end
end
Now suppose I want to update the definition of MyClass to be the following, which changes parts of the behavior of MyClass.
% MyClass.m
classdef MyClass < handle
properties
value (1,1) double
end
methods
function obj = MyClass()
obj.value = 100;
end
function v = getValue(obj)
v = obj.value;
end
function v = add(obj,a,b)
v = a - b;
obj.value = v;
end
end
end
Clearly, this second version of MyClass is not backward compatible, since it will break code that depends on the old behavior. For example, the 'add' method now subtracts its inputs as opposed to adding them.
How can I update the definition of MyClass in such a way that, when I load the old instances of MyClass from my MAT-file, they use the old class definition with the old behavior?

Best Answer

There are a number of ways that you can achieve this behavior of maintaining a single class with different behavior for different instances.
One simple approach is to use the strategy pattern:
With this design, you can have multiple class definitions with different behaviors but the same interface, which you can define with an interface class or an interface superclass (which helps avoid code duplication).
e.g.
% MyClass.m
classdef MyClass < handle
properties (Access = private)
instance
end
methods
function obj = MyClass(instance)
if nargin < 1
instance = MyClassV1();
end
obj.instance = instance;
end
function v = getValue(obj)
v = obj.instance.getValue();
end
function v = add(obj,a,b)
v = obj.instance.add(a,b);
end
end
end
------------------------------------------------
% MyClassV1.m
classdef MyClassV1 < handle
properties
value (1,1) double
end
methods
function obj = MyClassV1()
obj.value = 0;
end
function v = getValue(obj)
v = obj.value;
end
function v = add(obj,a,b)
v = a + b;
obj.value = v;
end
end
end
------------------------------------------------
% MyClassV2.m
classdef MyClassV2 < handle
properties
value (1,1) double
end
methods
function obj = MyClassV2()
obj.value = 100;
end
function v = getValue(obj)
v = obj.value;
end
function v = add(obj,a,b)
v = a - b;
obj.value = v;
end
end
end
------------------------------------------------
>> obj = MyClass;
>> obj.getValue()
ans =
0
>> obj.add(1,2)
ans =
3
>> save tmp obj
>> % change line 9 of MyClass.m to "instance = MyClassV2();"
>> clear obj
>> load tmp
>> obj.getValue()
ans =
3
>> obj.add(1,2)
ans =
3
>> newObj = MyClass;
>> newObj.getValue()
ans =
100
>> newObj.add(1,2)
ans =
-1