I am experiencing a problem with operator overloading of the subreferencing operator for a class. Below is an illustrative MATLAB value class that has a property, x, that stores a vector of integers. Operator overloading for () is implemented by overloading the subsref function.
classdef BizarreClass
properties
x;
end
methods
function obj = BizarreClass()
obj.x = [1 2 3 4 5];
end
function obj = setx(obj, x_val)
disp('called setx')
obj.x = x_val;
end
function varargout = subsref(obj, S)
if (strcmp(S(1).type, '()'))
disp('called for the right reason')
varargout{1} = obj.x(S(1).subs{1});
else
disp('called for the wrong reason')
varargout = {};
end
end
end
end
Now let's say I instantiate BizarreClass:
And then call the setx function to set x to a different value:
b = b.setx([1 3 5])
which gives an error:
Error in BizarreClass>BizarreClass.subsref (line 18)
if (strcmp(S(1).type, '()'))
Error using BizarreClass/subsref
Output argument "varargout" (and maybe others) not assigned during call to
"c:\users\johndoe\Desktop\swallowing\trunk\matlab_scripts\BizarreClass.m>BizarreClass.subsref".
This is happening because subsref is being called first (as it should). That is why I have logic that checks the input variable S and only handle the case where the object is subreferenced like b(3), in which case varargout gets the value indexed into the array, x. Otherwise, varargout is empty, which is the problem: The 'b = ' in 'b = setx([1 3 5])' needs to be there for the value of b to be updated. Unfortunately, this calls subsref first and not the setx method, causing that error.
I can get past this by calling setx on b like this:
But I want to call it like:
Is there a solution? How do I not have subsref to be called for any case other than the subsref operator? Or is there a design pattern that I should use that will allow me to use b = b.setx([1 3 5])