Add a event callback across all instances of class??

The idea is as follows:
If a property of an instance of class is changed, then all the instances of this class should take this property and do some update. The problem is I don't know how many instances of class exist, so I thought using event and listener could be a solution. Here is my code:
classdef myclass < handle
%EVENTTAKER Summary of this class goes here
% Detailed explanation goes here
properties
hf
sharedProp
end
events
sharedPropChanged
end
methods
function obj = myclass()
obj.sharedProp = rand(100, 2); % define prop as random data
obj.hf = figure;
plot(obj.sharedProp);
addlistener(obj,'sharedPropChanged',@obj.listenerCallback);
end
function setSharedProp(obj, newProp)
obj.sharedProp = newProp;
% broadcast event to all objects of class
notify(obj, 'sharedPropChanged');
end
function listenerCallback(obj, srcObj, ~)
obj.sharedProp = srcObj.sharedProp;
obj.update();
end
function update(obj)
plot(obj.sharedProp);
end
end
end
To test:
o1 = myclass; o2 = myclass;
o1.setSharedProp(rand(10, 2))
The result is that only the first instance get update, the second not.
Is this a plausible solution, or there is any way to implement this?
Thnks

 Risposta accettata

Guillaume
Guillaume il 28 Lug 2015
Modificato: Guillaume il 28 Lug 2015
What you're trying to create is a static property (belongs to the class not the instances). Matlab does not have that, but you could possibly emulate it with a constant property holding a reference to a handle class. Either make a lightweight handle class to wrap your static property or simply use a containers.Map with only one key:
classdef classwithstaticprop < handle
properties (Constant, GetAccess = private)
staticprop = containers.Map; %or just make a lightweight handle class
end
properties (Dependent)
sharedprop
end
methods
function this = classwithstaticprop() %constructor
if length(this.staticprop) == 0 %#ok<ISMT> isempty not defined for map
%first instance, initialise;
m = this.staticprop; %you have to use a local variable, see the doc
m('prop') = 1; %#ok<NASGU> %initialise to default value
end
end
function set.sharedprop(this, value)
m = this.staticprop;
m('prop') = value; %#ok<NASGU> %it's a handle
end
function value = get.sharedprop(this)
value = this.staticprop('prop');
end
end
end
See this page for why you have to use a local variable when changing the value of the handle class referred by the constant property.

6 Commenti

yes, i know this static property, but the main problem here is that from static property i can't invoke a event callback, which definitively needs a instance of class
Sorry, I missed that you also wanted to run some update code on property update.
The problem with your code is that the listener you create only listen to changes to its own owner, not to changes to all the other instances. With your design you would need to create, in each object, a listener per other object instances. And every time you'd create a new object, you'd have to go through all the previous one to add a new listener.
Instead, what you can do is still use a static property that is in fact a handle to an auxiliary class that actually contain the shared value. Each object can then just listen to the change of that shared object:
This is the main class:
classdef classwithstaticprop < handle
properties (Constant, GetAccess = private)
propwithupdate = staticprophelper
end
properties (Dependent)
sharedprop;
end
properties (Access = private)
lh; %listener handle
end
properties (SetAccess = private)
count;
end
methods
function this = classwithstaticprop() %constructor
persistent count;
if isempty(count), count = 1; else count = count+1; end
this.count = count;
%do not use addlistener, otherwise you can never clear classes
%the syntax for event.proplistener is a bit obscure
mc = ?staticprophelper;
this.lh = event.proplistener(this.propwithupdate, mc.PropertyList, 'PostSet', @this.doupdate);
end
function set.sharedprop(this, value)
this.propwithupdate.value = value;
end
function value = get.sharedprop(this)
value = this.propwithupdate.value;
end
end
methods (Access = private)
function doupdate(this, ~, ~)
fprintf('updating instance %d\n', this.count);
end
end
end
And this is the helper class, a singleton object is shared by all instances:
classdef staticprophelper < handle %has to be handle class
properties (Access = ?classwithstaticprop, SetObservable)
value = 0;
end
end
woah, that's lots of new things to me in M-OOP. Thanks, Guillaume
BTW, is there a way to "combine" two classdefs in to a single m-file? As far as I know, this is not possible. With two classdefs it is perhaps not so neat ...
No, you can only have one classdef per file. I have often wanted to do things like C++ namespaces with a class defined only for use within another class, but you cannot do that in one file.
Nor can you put classes in private folders, which would be another way of limiting the visibility of the utility class.
You cannot place multiple classes in the same file.
You cannot place class files in private folders.
You CAN place class files in package directories, however.

Accedi per commentare.

Più risposte (0)

Categorie

Tag

Richiesto:

il 28 Lug 2015

Commentato:

il 28 Lug 2015

Community Treasure Hunt

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

Start Hunting!

Translated by