MATLAB Answers

Listen for Changes to Property Values

27 views (last 30 days)
Nycholas Maia
Nycholas Maia on 22 Feb 2018
Answered: Jack Du Ho on 16 Aug 2019
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
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
Walter Roberson
Walter Roberson on 23 Feb 2018
You can use memoize and set the cache size to 1.

Sign in to comment.

Accepted Answer

Guillaume
Guillaume on 23 Feb 2018
Edited: Guillaume on 23 Feb 2018
If I understood correctly, wouldn't the following be the simplest way to implement what you want:
classdef (ConstructOnLoad) track < handle
properties (SetAccess = private) %I assume that rms cannot be set by the user
rms;
end
properties
signal = 1:10;
end
methods
function this = track()
this.UpdateRms();
end
function set.signal(this, value)
this.signal = value;
this.UpdateRms();
end
end
methods (Access = private)
function UpdateRms(this)
this.rms = rms(this.signal);
end
end
end
No need for dependent properties or listener. Just recalculate rms whenever signal is updated.
The ConstructOnLoad is there to ensure that rms is recalculated when a class object is reloaded from disk. It's not strictly necessary since rms and signal should never be out of sync even when read from disk.
  5 Comments
Nycholas Maia
Nycholas Maia on 23 Feb 2018
Fantastic! You all helped me a lot!
Thank you all!

Sign in to comment.

More Answers (3)

Steven Lord
Steven Lord on 22 Feb 2018
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
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.

Sign in to comment.


Gabriele Bunkheila
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
Nycholas Maia on 23 Feb 2018
Perfect Gabriele. As my project is large and I can not always re-calculate the value of object properties I believe the MATLAB SetObservable feature can be very useful to me.
The problem is that I am not able to run these features in this simple example I posted here.
I want whenever the 'signal' property changes, then trigger the 'update_rms' function, and update the value of the 'RMS' property.
Could you help me in the code from this example above posted using the SetObservable feature?

Sign in to comment.


Jack Du Ho
Jack Du 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

Tags

Products

Community Treasure Hunt

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

Start Hunting!