Clean way of writing a setter that can set nested private properties

Is there a clean way to write a setter for private properties/members that can accept nested properties?
Something with an API like:
function set(obj, property, value)
that can be called like:
obj.set('property_name.subproperty_name', value)
I can think of an easy but verbose way:
props = split(char(property), '.')
if numel(props) == 1
if obj.(props{1}) == value, return; end
obj.(props{1}) = value;
...
else if numel(props) == 2
...
end
or a way using setfield (but then all properties need to be public):
props = split(char(property), '.')
if getfield(obj, props{:}) == value, return; end
obj = setfield(obj, props{:}, value);
...
I am asking in case anyone knows a solution to this.
I want to have this in a custom setter because it checks if the variable has changed and it updates stuff if it has.
Thanks!

2 commentaires

Matt J
Matt J le 15 Fév 2023
Modifié(e) : Matt J le 15 Fév 2023
obj.set('property_name.subproperty_name', value)
Which property in the chain is supposed to be private, here? Do we assume subproperty_name is private to property_name? It shouldn't matter if property_name is private to class(obj). The set() method of class(obj) can access its private properties.
ErikJ GiesenLoo
ErikJ GiesenLoo le 15 Fév 2023
Modifié(e) : ErikJ GiesenLoo le 15 Fév 2023
Assume property_name is private. The set method can access private members, but implementation wise if I use getfield/setfield I cannot set 'property_name.subproperty_name' unless they are public. Conversely, I can try to assign obj.('property_name').('subproperty_name') but I'd have to check if props is split into 1, 2 or more nested properties (which is not clean imo).
I thought about using eval("obj" + property = value) but everyone says eval is evil, so I assume there is a better way.
Edit: I was looking thru the history of your comments and I think there is possibly a recursive way of writing it
Edit 2: I wrote a recursive function but it seems to make a copy of obj.(stuff) so it doesnt work

Connectez-vous pour commenter.

 Réponse acceptée

ErikJ GiesenLoo
ErikJ GiesenLoo le 15 Fév 2023
Modifié(e) : ErikJ GiesenLoo le 15 Fév 2023
Further responses are welcome this query, but here is one clunky alternative using a helper set_ function that takes in the base object two times (this and obj), a string array props (instead of cell array of chars), and the value to be assigned:
function [obj, update] = set_(this, obj, props, value)
if numel(props) > 1
[obj.(props(1)), update] = this.set_(obj.(props(1)), props(2:end), value);
else
update = ~isequal(obj.(props(1)), value);
obj.(props(1)) = value;
end
end
This needs to be called by a function set(this, props, value) as described in the question. the variable update tells set that a variable has changed and do further stuff. That further stuff cannot be called direcly at the base case of the helper set_ funciton because obj.(props(1)) needs to be reassigned to the base object.
Edit: changed helper function and now seems to work as expected

Plus de réponses (0)

Catégories

En savoir plus sur Loops and Conditional Statements dans Centre d'aide et File Exchange

Produits

Version

R2018b

Tags

Community Treasure Hunt

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

Start Hunting!

Translated by