Listen for Changes to Property Values

20 ビュー (過去 30 日間)
Nycholas Maia
Nycholas Maia 2018 年 2 月 22 日
回答済み: Dustin Ho 2019 年 8 月 16 日
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 件のコメント
Walter Roberson
Walter Roberson 2018 年 2 月 23 日
You can use memoize and set the cache size to 1.

サインインしてコメントする。

採用された回答

Guillaume
Guillaume 2018 年 2 月 23 日
編集済み: Guillaume 2018 年 2 月 23 日
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 件のコメント
Nycholas Maia
Nycholas Maia 2018 年 2 月 23 日
Fantastic! You all helped me a lot!
Thank you all!

サインインしてコメントする。

その他の回答 (3 件)

Steven Lord
Steven Lord 2018 年 2 月 22 日
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 件のコメント
Steven Lord
Steven Lord 2018 年 2 月 23 日
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
Gabriele Bunkheila 2018 年 2 月 23 日
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 件のコメント
Nycholas Maia
Nycholas Maia 2018 年 2 月 23 日
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?

サインインしてコメントする。


Dustin Ho
Dustin Ho 2019 年 8 月 16 日
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

タグ

製品

Community Treasure Hunt

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

Start Hunting!

Translated by