Listen for Changes to Property Values
Show older comments
I would like to update the RMS object property always when the signal object property has change:
classdef track < handle
properties
rms = 0;
end
properties (SetObservable)
signal = [1 2 3 4 5 6 7 8 9 10];
end
methods
function obj = update_rms(obj)
obj.rms = rms(obj.signal);
end
end
end
I don't understand very well the Matlab link: https://www.mathworks.com/help/matlab/matlab_oop/listening-for-changes-to-property-values.html#brkimdj-1
EXAMPLE:
% Init object:
myObj = track();
% Signal property manual update:
myObj.signal = [1 1 1 1];
% After this, I would like that myObj update automatically the RMS property calling the update_rms method.
Could you help me?
4 Comments
Nycholas Maia
on 23 Feb 2018
Steven Lord
on 23 Feb 2018
I assume this comment is related to my Answer. For that you might want to have your Dependent property's get.[property name] method use memoization via the memoize function.
Nycholas Maia
on 23 Feb 2018
Walter Roberson
on 23 Feb 2018
You can use memoize and set the cache size to 1.
Accepted Answer
More Answers (3)
Steven Lord
on 22 Feb 2018
0 votes
So you want the rms property to always be the result of calling the rms function on the signal property of your object? In that case I don't think you need property listeners. I would instead make rms a Dependent property. The "Calculate Data on Demand" section of this example in the documentation shows how to do this, where the Modulus property is calculated on demand from the Stress and Strain properties of that object.
1 Comment
Steven Lord
on 23 Feb 2018
If a Dependent property doesn't satisfy your needs, you could give the Signal property a property set method that computes and sets the RMS property. If you do that you probably want to restrict SetAccess to the RMS property so that only methods inside the class (private) or perhaps methods in that class and its subclasses (protected) can set it. If you left it with public SetAccess, anyone could change its value thus putting it out of sync with the Signal property's value.
Gabriele Bunkheila
on 23 Feb 2018
Hi Nycholas,
I agree with Steven's suggestion. Please find below a possible implementation of what I understand you are trying to achieve:
classdef track < handle
properties
signal = [1 2 3 4 5 6 7 8 9 10];
end
properties (Dependent)
RMS = 0;
end
properties (Access = private)
pRMS
end
methods
function obj = track()
update_rms(obj)
end
function set.signal(obj, value)
obj.signal = value;
update_rms(obj)
end
function set.RMS(obj,~)
fprintf('%s%g\n','RMS is: ',obj.RMS)
error('You cannot set the RMS property');
end
function value = get.RMS(obj)
value = obj.pRMS;
end
function update_rms(obj)
obj.pRMS = rms(obj.signal);
end
end
end
This would give you the following behavior:
>> t = track
t =
track with properties:
signal: [1 2 3 4 5 6 7 8 9 10]
RMS: 6.2048
>> t.signal = 0.1*t.signal
t =
track with properties:
signal: [0.1000 0.2000 0.3000 0.4000 0.5000 0.6000 0.7000 0.8000 0.9000 1]
RMS: 0.6205
>> t.RMS = 2
RMS is: 0.620484
Error using track/set.RMS (line 21)
You cannot set the RMS property
>>
You can simplify this to avoid storing anything, at the expense of triggering a computation every time you need to use or display the RMS property.
I hope this helps.
Gabriele.
4 Comments
Nycholas Maia
on 23 Feb 2018
Adam
on 23 Feb 2018
The private property is there precisely to store the values, the public dependent property does not store any data, which is always the case with a dependent property.
It simply asks the private property for the value when you ask for the public RMS value.
In this setup the paired property that actually stores the value should always be private because you access it via the public RMS property.
In this particular usage I would agree with Guillaume though that it seems un-necessary.
I use this kind of setup generally when I want to be able to publicly set the RMS value and in that set function to also refer to some other class property (e.g. for validation).
Gabriele Bunkheila
on 23 Feb 2018
Hi Nycholas,
Dependent properties do not store data but compute it based on other values (e.g. stored in other properties). Because they don't store data, when queried (i.e. in their get method) they need to either compute it or copy from somewhere else. The role of pRMS is to store the value so you don't need to re-compute it every time that you need it.
That said, Guillaume's take below without using Dependent attributes is equally valid (and shorter) in this simple case.
On the other hand, the SetObservable qualifier allows you to create listeners for property-set events - it is a more complicated tool. I agree it doesn't seem justified for this simple example, but it may be useful in larger-scale problems. One of the benefits that I found in using listeners in the past is the effectiveness in decoupling triggering events (in this case the change of the value of a property) from the resulting effect - the property change does not need to know what needs to happen next.
Good luck with your project,
Gabriele.
Nycholas Maia
on 23 Feb 2018
Edited: Nycholas Maia
on 23 Feb 2018
Dustin Ho
on 16 Aug 2019
One solution is to define an event "signalChanged" and create a listener when you initialize the object
classdef track < handle
properties
rms = 0;
end
properties
signal = [1 2 3 4 5 6 7 8 9 10]
end
events
signalChanged
end
methods
function obj = track()
obj.update_rms;
addlistener(obj,'signalChanged',@(~,~) obj.update_rms);
end
function obj = disp(obj)
disp('--------------------------')
disp(obj.rms);
disp('--------------------------')
end
function set.signal(obj,value)
obj.signal = value;
notify(obj,'signalChanged')
end
function update_rms(obj)
obj.rms = rms(obj.signal);
end
end
end
Categories
Find more on AI for Signals in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!