Set Methods for Dynamic Properties with Unknown Names
14 次查看(过去 30 天)
显示 更早的评论
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 个评论
Jarmo Ritola
2012-12-14
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
回答(3 个)
Max
2015-5-19
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
0 个评论
Jim Hokanson
2013-6-10
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 个评论
Jim Hokanson
2013-6-27
Just tried this recently. There is an additional check on a scalar function handle so the empty assignment does not work.
Guangzhi
2014-10-24
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)
0 个评论
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Properties 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!