How to efficiently use dependent properties if dependence is computational costly?

Hello!
I want to design a class where some properties are dependent on others. I understand the general concept of Matlab OOP for dependent properties: the property is recalculated each time it is accessed.
But if these calculations/dependencies are costly and the dependent properties are often accessed by methods within the class, what are you suggesting to do. Basically, it would suffice to recalculated the property each time its parents properties are updated.
If I do so, I get a warning that accessing another property from the set method of an independent property is not recommended. What else can I do?
Cheers Michael

 Accepted Answer

I would recommend you add a method to compute and update the value of your dependent property and then call that method from the setters for each property that updates it. This single-sources the computation of that property, caches it to avoid unnecessary re-computation, and satisfies MATLAB Code Analyzer.
Here is an example, where Area of a Rectangle depends on Width and Height and is updated when each of those is set:
classdef Rectangle < handle
properties
Width = 10;
Height = 20;
end
properties(SetAccess = private)
Area = 200;
end
methods
function set.Width(obj, v)
obj.Width = v;
obj.updateArea;
end
function set.Height(obj, v)
obj.Height = v;
obj.updateArea;
end
end
methods(Access = private)
function updateArea(obj)
obj.Area = obj.Width * obj.Height;
end
end
end

8 Comments

I just want to thank you for this example. The
properties(SetAccess = private)
bit is exactly what I was looking for. I think there is a lot of confusion around Dependent properties because people tend to begin learning about classes "on the job" and have an application in mind. Dependent can mean a lot of things, and I think many approach Dependent properties as if they simply mean "Derived from some function of other properties". In fact, it means "Always computed on the fly". You could use an active variable to keep an always-accurate list of files in a directory, for example, which need not interact with any other properties. Once I started thinking about Dependent properties as "Active", and internalized the significance that set methods cannot be used in conjunction with them, it all became more clear.
Most examples utilize a private "mirror" of the critical property that is not dependent, and then have the get method associated with public-facing dependent variable reference that private mirror (e.g., this similar thread). It is kind of a mess, and gives the false impression that a Dependent property is essential for the use case where you want a variable to update every time some other properties are set. In other words, every other example I have seen has forced Dependent properties into the solution, but they are not needed.
So, if you want a property to update whenever another property is set, and prevent it being directly changed by the user, the example provided above is a great template. If, on the other hand, you want a property to never store a value, but to instead essentially store a method that will generate a value on the fly when referenced, then you should use a Dependent property. These imply are quite different use cases, both involving dependency... which comes around to my main point that "Dependent" is kind of an unfortunate bit of language here.
Thanks to both of you!
I had exactly this confusion, and this clears it up a bit for me. However, I am not completely on board with when to use "Dependent" variables. That is, the propertes that are computed on the fly. I guess I don't really understand your example with "active" variable and files in a directory.
Why are dependent properties ever necessary? When can you not just use a method instead of the get.dependentProperty() ?
That is, why use:
properties(Dependent = true)
dependentProperty
end
methods
function output = get.dependentProperty()
*something*
end
end
instead of:
methods
function output = normalMethod()
*something*
end
end
?
Often dependent properties can be useful when you define property getters and setters. Suppose you had a Circle class with two properties, a normal one Radius and a Dependent property named Area. The property get method for Area would use the current value of Radius. The property set method for Area would determine the Radius for a Circle with that area.
classdef Circle
properties
Radius
end
properties(Dependent)
Area
end
methods
function obj = Circle(r)
if nargin == 0
obj.Radius = 0;
elseif isa(r, 'Circle')
obj = r;
else
obj.Radius = r;
end
end
function a = get.Area(obj)
a = pi*obj.Radius.^2;
end
function obj = set.Area(obj, a)
r = sqrt(a./pi);
obj.Radius = r;
end
end
end
Try creating a Circle with Radius 1. Then change the Radius of that object to 2 and note the automatic change to the Area. Finally set the Area of the Circle to pi and note that the Radius updates back to 1.
If neither property was Dependent you could set incompatible Radius and Area properties on the object.
You could have multiple properties that are both Dependent on the same concrete property, like a Perimeter or a Circumference property of the Circle object.
Ok, thanks! I think this makes a little clearer.
One thing that bothers me is that the dependent variable is recomputed every time you get its value. Though, upon trying some workarounds that don't use dependent variables, I think I understand that they are convenient for their purpose.
What is a good way to structure your class (best practice) such that a variable that is dependent on another variable can be stored and not recomputed all the time, but still remain valid with respect to the other variable?
That is, f.ex., if you use the value of the area very often during computations, but once in a while it is updated because the radius changed.
I would naturally think that I could do this:
classdef Circle
properties
Radius
Area
end
methods
function obj = Circle(r)
obj.Radius = r;
end
function obj = set.Radius(obj, r)
obj.Radius = r;
obj.Area = pi*r.^2;
end
end
end
But now I loose the ability to set the area directly, and have the radius computed. I could add a "set.Area" function to set the radius, but that causes a reccursion problem. Is there a way to get both of these properties? (1. store the area as number for quick access, 2. have both the area and radius updated when the other is changed)
Make another Hidden private property to cache the stored result, set that Hidden property to empty if you change a value used to compute it, and only recompute if the Hidden property is empty?
Or use the memoize function to define a property of the object. If you call the memoized function with the same inputs, it will return the cached answer without calling the function again.
m = memoize(@functionWithPause);
tic
y1 = m(1)
y1 = 2
toc
Elapsed time is 3.087905 seconds.
tic
y2 = m(2)
y2 = 4
toc
Elapsed time is 3.015403 seconds.
tic
y3 = m(1)
y3 = 2
toc
Elapsed time is 0.014966 seconds.
If that last call had called functionWithPause again, it would have taken over 3 seconds. Instead it reused the cached value from the first call, the one that created y1.
function z = functionWithPause(x)
z = 2*x;
pause(3)
end
I'm using that pattern in handle classes too, but how to implement it in value classes? Updating dependent properties in the update Method does not work because the setter & getter do not return the object.
Thanks :)
It would be a nice addition to the Matlab language if there were a "Dependent = push" option or similar (vs. a default of "Dependent = pull") which could automatically execute the equivalent of the set and update methods that @Jacob Halbrooks defines above. It would save the programmer a lot of refactoring effort whenever it's discovered that the "push" paradigm is more efficient than "pull".

Sign in to comment.

More Answers (0)

Categories

Find more on Sample Class Implementations 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!