How to efficiently use dependent properties if dependence is computational costly?
You are now following this question
- You will see updates in your followed content feed.
- You may receive emails, depending on your communication preferences.
An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Show older comments
1 vote
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
Jacob Halbrooks
on 8 May 2014
Edited: Jacob Halbrooks
on 8 May 2014
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
Chris
on 22 Apr 2017
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.
Trym Gabrielsen
on 22 Oct 2023
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
Trym Gabrielsen
on 26 Oct 2023
Ok, thank you so much!
Jan Kappen
on 5 Mar 2024
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 :)
Vaughan Clarkson
on 28 May 2024
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".
More Answers (0)
Categories
Find more on Sample Class Implementations in Help Center and File Exchange
See Also
on 8 May 2014
on 28 May 2024
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)