Set Methods for Dynamic Properties with Unknown Names

18 views (last 30 days)
Hi Everyone,
I have been working with a class that has dynamic properties that I would like to implement set methods for. The problem is that I don't know what the names of the properties will be until runtime, so I can't just say obj.prop = val in the set method. Here's an example class definition where I take a property name and value as arguments to the constructor, and try to turn that into a dynamic property with a set method:
classdef MyClass < dynamicprops
methods
function obj = MyClass(propname, val)
P = obj.addprop(propname);
P.SetMethod = @(o,p)setProp(o,propname,p);
obj.(propname) = val;
end
function setProp(obj, propname, val)
% do other stuff
obj.(propname) = val;
end
end
end
This unfortunately creates an infinite loop between setProp and @(o,p)setProp(o,propname,p), since they are distinct functions. I'm pretty sure I need to make SetMethod something of the form @mysetfcn (with no input args) to avoid this, but I don't know how to make that function aware of the name of the property that is being set (so that I can actually set it). The variable P has the property name as a field, so getting access to that within the function would also be good enough.
One fix is to overload subsasgn, however in my particular case I am also subclassing matlab.mixin.Heterogeneous which disallows that. It also just seems like there should exist a solution avoiding that, since I assume most people using dynamicprops won't know their property names.
Thanks in advance for any help or ideas!
  1 Comment
Jarmo Ritola
Jarmo Ritola on 14 Dec 2012
Dear Andrew, I wonder whether you have found a solution? I was searching a solution for a similar application and I found you question. Your question answered my problem of knowing the name of the field I am accessing. At least as a work around for your question, I would suggest that you make your dynamic fields also Dependent (P.Dependent=true). Then use two (hidden) cell array fields 'propnames' and 'propvalues' to actually store the names and values. In addition to the SetMethod, define also the GetMethod, and in both methods search the location of 'propname' in 'propnames' and then index into 'propvalues' to either write or read its value. This works fine in my application. The following is a simple example:
classdef testdynprop < dynamicprops %TESTDYNPROP simply testing with dynamic properties
properties
propnames = {};
propvalues = {};
end
methods
function obj=newdynprop(obj,name)
prop = obj.addprop(name);
prop.Dependent = true;
prop.GetMethod = @(obj)getDynPropValue(obj,name);
prop.SetMethod = @(obj,value)setDynPropValue(obj,name,value);
N = length(obj.propnames)+1;
obj.propnames{N}=name;
obj.propvalues{N} = [];
end
function val = getDynPropValue(obj,name)
val = obj.propvalues{find(strcmp(obj.propnames,name))};
end
function obj = setDynPropValue(obj,name,value)
obj.propvalues{find(strcmp(obj.propnames,name))} = value;
end
end
end

Sign in to comment.

Answers (3)

Max
Max on 19 May 2015
I also needed an answer to this question. Adding listeners might be the right way to go but I actually found Jarmo's response easier to understand and implement. Ultimately this is the approach I followed, though I used a 'struct' as a container for my dynamic properties as in the example below:
classdef MyClass < dynamicprops
properties (Hidden)
container
end
methods
function obj = addDynamicProp(obj,name)
prop = obj.addprop(name);
prop.Dependent = true;
prop.GetMethod = @(obj)getDynamicProp(obj,name);
prop.SetMethod = @(obj,val)setDynamicProp(obj,name,val);
obj.container.(name) = [];
end
end
end
function val = getDynamicProp(obj,name)
val = obj.container.(name);
end
function setDynamicProp(obj,name,val)
obj.container.(name) = val;
end

Jim Hokanson
Jim Hokanson on 10 Jun 2013
You could add a listener that on pre set assigns the name to the object ...
Basically just before you actually set the property, you update the property with the name of the property you are about to set, which you can then use in the set method.
I had also tried temporarily undoing the set method in the set method (and then reassigning after the actual assignment) but it is not possible to set the SetMethod value to [], as it is looking for a function handle.
classdef myClass < dynamicprops
properties
set_prop
end
methods
function obj = myClass()
P = addprop(obj, 'myProp');
P.SetObservable = true;
addlistener(obj,'myProp','PreSet',@obj.preSet);
P.SetMethod = @SetProp;
end
function SetProp(obj, val)
obj.(obj.set_prop) = val;
end
end
methods (Static)
function preSet(src,evnt)
evnt.AffectedObject.set_prop = src.Name;
end
end
end
  3 Comments
Jim Hokanson
Jim Hokanson on 27 Jun 2013
Just tried this recently. There is an additional check on a scalar function handle so the empty assignment does not work.
Rajmohan
Rajmohan on 19 May 2022
Could this approach cause issues if using parallel processing?
Thanks!

Sign in to comment.


Guangzhi
Guangzhi on 24 Oct 2014
I am rather new to Matlab so I am not entirely sure I understood your problem. Are you trying to assign new properties to a class object, but the name of the new property is not known before hand?
In that case, will this help solve the issue?
Put the property assignment command in a string, and use the eval() function to execute the command, like this:
newpropname=func_that_returns_a_string();
newpropvalue=func_that_returns_a_value();
myobj.addprop(newpropname);
tmpstr=['myobj.', newpropname, '=newpropvalue'];
eval(tmpstr)

Categories

Find more on Properties in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!