Matlab OOP, dependent class properties, correct coding techiques

7 views (last 30 days)
Hi,
I have a conceptual problem I'm struggling with and was wondering if anyone could give some insight into this.
Essentially, I have a class with three (or more) properties. Watered down Pseudo code below:
classdef obj
Properties
A
B
C
end
Methods
constructor etc
function set.A
C = f(obj.A,obj.B) % C is dependent on A and B (MLINT warns on this line)
A = inputValue % Set A's value
end
end
end
Now herein lies the problem as I'm sure you have already noticed. I'm setting one properties value while changing another property's value. MLINT warns immediately that this is bad and correctly states that one should make C a dependent property.
This is fine unless speed is an issue. C is going to be called "lots of times". And having Matlab calculate it every time
*get.C*
is called is expensive. A and B will be updated through out the life of the object and hence I want C recalc'ed on the fly when they do.
Should I disregard MLINT (and probably good coding practice)?
Is there a better but still fast way to achieve what I want?
Regards, Phil
  1 Comment
Phillip
Phillip on 31 Mar 2015
Hi
Clearly I should have searched better for answers to this as there are numerous ones.
Apologies for bringing it up again. However, if someone has some more insight into this it would be greatly appreciated.
Regards,
Phil

Sign in to comment.

Accepted Answer

Adam Wyatt
Adam Wyatt on 31 Mar 2015
Edited: Adam Wyatt on 31 Mar 2015
I generally just ignore this warning - you can turn it off for the line, file or all files (I've done the latter).
In your scenario, there's probably not an issue, but there are situations when there could be.
The best practise would be to use events & listeners - add a listener that waits for A to change. You can even use the built in event PreSet/PostSet. Search for "Listen for Changes to Property Values" in the documentation.
Indeed you do not want to make C dependent. In that scenario, you would not even use the first line
C = f(obj.A, obj.B)
because C cannot be set (in the normal sense)
  2 Comments
Phillip
Phillip on 31 Mar 2015
Edited: Phillip on 31 Mar 2015
Hi Adam
Thanks for the response. Ignoring it could jeopardize save and load functionality but I see you can intervene in that process by defining loadobj and saveobj? Could this be used to ensure properties are loaded in correct order?
I have thought about events/listeners and will investigate.
On thing I didn't mention is further dependencies of properties. A and B also need to be checked against one another (ie. same type of dimensions) and checked against other parameters. This makes things tricky. Because if the checks fail then C cannot be calculated. What happens to C in that case, set it back to original value etc?
Ultimately I think I will need to force the user to input/update in a very specific order. Ie. B cannot be updated/initialized with A being initialized first etc.
Adam Wyatt
Adam Wyatt on 1 Apr 2015
With regards to saving / loading, yes you could implement specific save/load methods. You can also specify variables as transient. I normally do the first option.
It sounds like you have quite a complex dependency between variables. In this case, you might not want to allow arbitray setting of the variables (i.e. make them private/protected) and use a single function SetParameters. I often use property name/value pairs for this purpose. You can make use of matlabs varargin variable or empty parameter inputs to allow the user to specify a subset of variables e.g.
function SetParameters(obj, varargin)
...
end
% Usage:
obj.SetParameters('b', <value>);
function SetParameters(obj, a, b, ...)
...
end
% Usage:
obj.SetParameters([], b);
I'm not sure if the PreSet/PostSet functions run recursively (i.e. if you change a, notify change in a, change b due to listener on a, notify b, change a due to listener on b ... Also, if you change a, update c, change b, update c, that's not ideal.

Sign in to comment.

More Answers (1)

Adam
Adam on 31 Mar 2015
Edited: Adam on 31 Mar 2015
The usual solution to that is to make A dependent, not C. It is a less common usage of dependent properties to make use of the set function as well as the get function, but in this case that is one of the simplest solutions.
The set function for a dependent property is allowed to set other class properties (without giving any warning - i.e. in a robust way).
e.g. (code isn't perfect, but I left in some pseudo-code of yours rather than compilable Matlab code)
classdef obj
Properties
A
B
C
end
Properties( Access = private )
A_
end
Methods
function set.A
C = f(obj.A,obj.B)
A_ = inputValue;
end
function A = get.A( obj )
A = obj.A_;
end
end
end
C remains exactly as it is, though I would assume from this that you want C to have private set access.
  3 Comments
Adam
Adam on 31 Mar 2015
In response to the Phillip's comment about further dependencies...
If I have two properties that want to be validated against each other or for some other reason basically need to be assigned both at the same time I just make their set property private and create my own function which takes both of them as arguments so you can only set them together.
Such a function also has no limitations on what other properties it is allowed to set or access.
Phillip
Phillip on 1 Apr 2015
Adam
Thanks for all the thoughts and ideas. All of them has a place.
Will plough through the solutions and see what works best.

Sign in to comment.

Products

Community Treasure Hunt

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

Start Hunting!