Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dependent observable property in Matlab. Does it work?

In Matlab class it seems to be syntactically correct to declare property that is Dependent (computed not stored) and Observable in the same time. Consider code

properties (Access = private)
    instanceOfAnotherClass
end
properties (SetAccess = private, Dependent, SetObservable)
    propertyTwo
end
methods
    function val = get.propertyTwo(this)
        val = this.instanceOfAnotherClass.propertyOne;   
    end
end

Does this work as expected? That is, if the property propertyOne of an object stored in instanceOfAnotherClass is changed is there property change event triggered by propertyTwo? Note that propertyOne is not Observable.

Edit: It does not work (as I expected). 'PostSet' event is not triggered. So how do I deal with this kind of situation? Is there a better solution then to create propertyTwo as a non Dependent and set it to the same value as 'propertyOne' every time 'propertyOne' changes?

Edit2: In reaction to Amro's edit of his answer I will explain situation more complex. Consider this 2 classes:

 classdef AClass < handle
     properties
         a
     end
 end
 classdef BClass < handle
     properties (Access = private)
         aClassInst
     end
     properties (Dependent, SetObservable, SetAccess = private)
         b
     end
     methods
         function this = BClass(aClass)
             this.aClassInst = aClass;
         end
         function val = get.b(this)
             val = this.aClassInst.a;
         end
     end
 end

The class that uses all this code should not get access to AClass. It interacts only with instance of BClass and wants to listen to changes of property b. however if I make property a of AClass observable that would not solve my problem, would it? The 'PostSet' events are not going to propagate to property b, are they?

like image 555
Rasto Avatar asked Jul 25 '12 14:07

Rasto


People also ask

What is a dependent property MATLAB?

Dependent properties do not store data. The value of a dependent property depends on some other value, such as the value of a nondependent property. Dependent properties must define get-access methods ( get. PropertyName ) to determine a value for the property when the property is queried.

What Does properties do in MATLAB?

Properties contain object data. Classes define the same properties for all object, but each object can have unique data values. Property attributes control what functions or methods can access the property. You can define functions that execute whenever you set or query property values.

What is a Classdef in MATLAB?

What Is a Class Definition. A MATLAB® class definition is a template whose purpose is to provide a description of all the elements that are common to all instances of the class. Class members are the properties, methods, and events that define the class.


1 Answers

It might be syntactically correct, but the listener callback will never execute. Example:

classdef MyClass < handle
    properties (Access = public)
        a
    end
    properties (SetAccess = private, Dependent, SetObservable)
        b
    end
    methods
        function val = get.b(this)
            val = this.a;
        end
    end
end

Now try:

c = MyClass();
lh = addlistener(c, 'b', 'PostSet',@(o,e)disp(e.EventName));
c.a = 1;
disp(c.b)

As you can see the 'PostSet' callback is never executed.


EDIT

The way I see it, SetObservable should really be set on a not b. Its because b is read-only and can only change if a changes. Now the PostSet event would notify us that both properties have changed.

Use the same example I used above, simply move SetObservable from b to a. Of course now you listen to the event as:

lh = addlistener(c, 'a', 'PostSet',@(o,e)disp(e.EventName));

EDIT#2

Sorry I didn't pay attention to the fact that you have composition (BClass has an instance of AClass as private property).

Consider this possible solution:

AClass.m

classdef AClass < handle
    properties (SetObservable)
        a                        %# observable property
    end
end

BClass.m

classdef BClass < handle
    properties (Access = private)
        aClassInst               %# instance of AClass
        lh                       %# event listener on aClassInst.a
    end
    properties (Dependent, SetAccess = private)
        b                        %# dependent property, read-only
    end
    events (ListenAccess = public, NotifyAccess = private)
        bPostSet                 %# custom event raised on b PostSet
    end
    methods
        function this = BClass(aClass)
            %# store AClass instance handle
            this.aClassInst = aClass;
            %# listen on PostSet event for property a of AClass instance
            this.lh = addlistener(this.aClassInst, 'a',  ...
                'PostSet', @this.aPostSet_EventHandler);
        end
        function val = get.b(this)
            val = this.aClassInst.a;
        end
    end
    methods (Access = private)
        function aPostSet_EventHandler(this, src, evt)
            %# raise bPostSet event, notifying all registered listeners
            notify(this, 'bPostSet')
        end
    end
end

Basically we set property a of AClass as observable.

Next inside the constructor of BClass, we register a listener for the AClass instance passed to listen on property a changes. In the callback we notify listeners of this object that b has changed as well

Since we can't really raise a PostSet manually, I created a custom event bPostSet which we raise in the previous callback function. You can always customize the event data passed, refer to the documentation to see how.

Here is a test case:

%# create the objects
a = AClass();
b = BClass(a);

%# change property a. We will not recieve any notification
disp('a.a = 1')
a.a = 1;

%# now lets listen for the 'bChanged' event on b
lh = addlistener(b, 'bPostSet',@(o,e) disp('-- changed'));

%# try to change the property a again. We shall see notification
disp('a.a = 2')
a.a = 2;

%# remove event handler
delete(lh)

%# no more notifications
disp('a.a = 3')
a.a = 3;

The output was:

a.a = 1
a.a = 2
-- changed
a.a = 3

Notice how we only interact with the BClass instance when we register our listener. Of course since all classes derive from handle class, the instance a and the private property aClassInst both refer to the same object. So any changes to a.a are immediately reflected on b.aClassInst.a, this causes the internal aPostSet_EventHandler to execute, which in turn notify all registered listeners to our custom event.

like image 171
Amro Avatar answered Oct 30 '22 19:10

Amro