6

Matlabクラスでは、 Dependent(計算されて保存されていない) であると同時にObservableであるプロパティを宣言することは構文的に正しいようです。コードを検討する

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

これは期待どおりに機能しますか?つまり、にpropertyOne格納されているオブジェクトのプロパティinstanceOfAnotherClassが変更された場合、?によってトリガーされるプロパティ変更イベントがありますpropertyTwoか?はObservablepropertyOneではないことに注意してください。

編集: それは機能しません(私が期待したように)。「PostSet」イベントはトリガーされません。では、このような状況にどのように対処すればよいでしょうか。propertyTwo依存として作成し、 「propertyOne」が変更されるたびに「propertyOne」と同じ値に設定するより良い解決策はありますか?

Edit2:Amroの 回答の編集に 応じて、状況をより複雑に説明します。この2つのクラスを検討してください。

 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。しかし、私が自分の問題を解決しないオブザーバブルのプロパティを作成した場合、それaは可能でしょうか?AClass'PostSet'イベントはプロパティに伝播されませんbね。

4

1 に答える 1

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

今試してみてください:

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イベントは両方のプロパティが変更されたことを通知します。

上で使用したのと同じ例を使用して、SetObservableからに移動baます。もちろん今、あなたは次のようにイベントを聴きます:

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

基本的にa、AClassのプロパティを監視可能として設定します。

次に、BClassのコンストラクター内で、プロパティの変更をリッスンするために渡されたAClassインスタンスのリスナーを登録しますabコールバックでは、このオブジェクトも変更されたことをリスナーに通知します

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;

出力は次のとおりです。

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

リスナーを登録するときにのみBClassインスタンスと対話する方法に注意してください。もちろん、すべてのクラスはクラスから派生しているためhandle、インスタンスaとプライベートプロパティaClassInstは両方とも同じオブジェクトを参照します。したがって、への変更a.aはすぐに反映されますb.aClassInst.a。これにより、内部aPostSet_EventHandlerが実行され、登録されているすべてのリスナーにカスタムイベントが通知されます。

于 2012-07-25T15:23:18.460 に答える