Matlab中的相关可观察属性.它有用吗?

Ras*_*sto 6 oop events matlab properties event-handling

在Matlab的类这似乎是语法正确申报财产依赖(计算不存储)和 可观察到在同一时间.考虑代码

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

这是否按预期工作?也就是说,如果propertyOne存储的对象的instanceOfAnotherClass属性发生更改,则会触发由propertyTwo?触发的属性更改事件.请注意,这propertyOne不是Observable.

编辑: 它不起作用(如我所料).不会触发'PostSet'事件.那么我该如何处理这种情况呢?是否有更好的解决方案,然后创建propertyTwo依赖项,并在每次'propertyOne'更改时将其设置为与'propertyOne'相同的值?

编辑2 : 为了回应Amro 对他的回答编辑,我将解释更复杂的情况.考虑这两个类:

 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
Run Code Online (Sandbox Code Playgroud)

使用所有此代码的类不应该访问AClass.它只与实例进行交互,BClass并希望收听属性的变化b.但是,如果我制作aAClass不能解决我问题的可观察属性,那么呢?'PostSet'事件不会传播到属性b,是吗?

Amr*_*mro 3

它在语法上可能是正确的,但侦听器回调永远不会执行。例子:

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
Run Code Online (Sandbox Code Playgroud)

现在尝试:

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

正如您所看到的,“PostSet”回调从未执行。


编辑

在我看来,SetObservable确实应该设置为anot b。这是因为b它是只读的,并且只有在a更改时才能更改。现在该PostSet事件会通知我们两个属性都已更改。

使用我上面使用的相同示例,只需SetObservable从移动ba。当然,现在您可以按照以下方式收听该事件:

lh = addlistener(c, 'a', 'PostSet',@(o,e)disp(e.EventName));
Run Code Online (Sandbox Code Playgroud)

编辑#2

抱歉,我没有注意到您具有组合这一事实(BClass 有一个 AClass 实例作为私有财产)。

考虑这个可能的解决方案:

A类.m

classdef AClass < handle
    properties (SetObservable)
        a                        %# observable property
    end
end
Run Code Online (Sandbox Code Playgroud)

B类.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
Run Code Online (Sandbox Code Playgroud)

基本上我们将aAClass 的属性设置为可观察的。

接下来,在 BClass 的构造函数中,我们为传递的 AClass 实例注册一个侦听器,以侦听属性a更改。在回调中,我们通知侦听器该对象b也已更改

由于我们无法真正PostSet手动引发,因此我创建了一个bPostSet在前面的回调函数中引发的自定义事件。您始终可以自定义传递的事件数据,请参阅文档了解如何操作。

这是一个测试用例:

%# 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;
Run Code Online (Sandbox Code Playgroud)

输出是:

a.a = 1
a.a = 2
-- changed
a.a = 3
Run Code Online (Sandbox Code Playgroud)

请注意,当我们注册侦听器时,我们如何仅与 BClass 实例进行交互。当然,由于所有类都派生handle自类,因此实例a和私有属性aClassInst都引用同一个对象。因此,对 的任何更改都会a.a立即反映在 上b.aClassInst.a,这会导致内部aPostSet_EventHandler执行,进而通知所有已注册的侦听器我们的自定义事件。