【问题标题】:Dependent observable property in Matlab. Does it work?Matlab 中的相关可观察属性。它有效吗?
【发布时间】:2012-07-24 00:49:24
【问题描述】:

在 Matlab 类中,同时声明 Dependent(计算未存储)和 Observableproperty 似乎在语法上是正确的.考虑代码

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

这是否按预期工作?也就是说,如果存储在instanceOfAnotherClass 中的对象的属性propertyOne 发生更改,是否有propertyTwo 触发的属性更改事件?请注意,propertyOne 不是可观察的

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

编辑2: 针对Amro'sedit of his answer,我将解释更复杂的情况。 考虑这两个类:

 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

使用所有这些代码的类不应访问AClass。它只与BClass 的实例交互,并希望监听b 属性的变化。但是,如果我将aAClass 的属性设为可观察的,那将无法解决我的问题,对吗? 'PostSet' 事件不会传播到属性 b,是吗?

【问题讨论】:

  • 你为什么不在一个最小的测试例子上测试它?
  • @mutzmatron 好点:)我可以自己测试。但事实上,我希望它不起作用,并想要一些关于如何使它起作用的想法......或者关于这类问题的良好实践。这次我应该编辑我的问题并提出正确的问题。

标签: oop events matlab properties event-handling


【解决方案1】:

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

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

现在试试:

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

如您所见,'PostSet' 回调从未执行。


编辑

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

使用我上面使用的相同示例,只需将 SetObservableb 移动到 a。当然,现在您可以这样收听事件:

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

编辑#2

对不起,我没有注意到你有组合(BClass 有一个 AClass 的实例作为私有属性)。

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

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

基本上我们将 AClass 的属性 a 设置为 observable。

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

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

这是一个测试用例:

%# 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;

输出是:

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

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

【讨论】:

  • 这正是我所期望的……但我不喜欢它。有什么方法可以让它工作吗?如果 a 是可观察的呢? 'PostSet' 会执行吗?我在这台电脑上没有 Matlab 来尝试它。如果不是,我会做什么外壳以使其正常工作?
  • @drasto:查看我的编辑。我建议您将属性 a 设置为 SetObservable 而不是 b
  • 好吧,我可以这样做,但是客户端类无法访问属性a,因为它是不同类的属性。所以客户端类不能直接监听a的变化。有关详细信息,请参阅我的编辑。
  • 谢谢。没有我想要的那么清楚,但我想已经足够接近了。如果有更多回复,我会等待,如果没有,我会接受您的回复。再次感谢您。
猜你喜欢
  • 1970-01-01
  • 2017-09-07
  • 2020-11-20
  • 1970-01-01
  • 2015-11-30
  • 2021-11-22
  • 2018-06-14
  • 2021-03-30
  • 1970-01-01
相关资源
最近更新 更多