Set Methods for Dynamic Properties with Unknown Names

19 vues (au cours des 30 derniers jours)
Andrew Barton
Andrew Barton le 22 Sep 2012
Commenté : Rajmohan le 19 Mai 2022
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 commentaire
Jarmo Ritola
Jarmo Ritola le 14 Déc 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

Connectez-vous pour commenter.

Réponses (3)

Max
Max le 19 Mai 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 le 10 Juin 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 commentaires
Jim Hokanson
Jim Hokanson le 27 Juin 2013
Just tried this recently. There is an additional check on a scalar function handle so the empty assignment does not work.
Rajmohan
Rajmohan le 19 Mai 2022
Could this approach cause issues if using parallel processing?
Thanks!

Connectez-vous pour commenter.


Guangzhi
Guangzhi le 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)

Catégories

En savoir plus sur Properties dans Help Center et File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by