2012-03-04 5 views
2

私は2つのクラス、PlantGeneratorを持っています。 Generatorは、ベクトルを作成し、notify()でブロードキャストします。Plantはこれを待ちます。 classdefは以下の通りです。私は実際のデータ生成方法を含めていないことに注意してください。なぜなら、それは私の質問には無関係だからです。私はGeneratorデストラクタが奇妙な本当に振る舞うことに気づいMATLAB - リスナーが関与するときにオブジェクトデストラクタが実行されない

classdef Plant < handle 
    properties 
     Listener 
    end 
    methods 
     function ListenerCallback(obj, data) 
      #% Perform an operation on data 
     end 
    end 
end 

classdef Generator < handle 
    properties 
     plant 
    end 
    events 
     newSignal 
    end 
    methods 
     function obj = Generator(plant) 
      obj.plant = plant; 
      obj.plant.Listener = addlistener(obj, 'newSignal', ... 
       @(src, data) obj.plant.ListenerCallback(data)); 
     end 
     function delete(obj) 
      delete(obj.plant.Listener); 
      disp('Generator instance deleted'); 
     end 
    end 
end 

:私はGeneratorインスタンスを削除し、その後初めて作成し、それは私がGeneratorインスタンスを作成する二時までデストラクタを実行しません。ここに例があります:

>> P = Plant 
P = 
    Plant handle 

    Properties: 
    Listener: [] 
    Methods, Events, Superclasses 

>> G = Generator(P) 
G = 
    Generator handle 

    Properties: 
    plant: [1x1 Plant] 
    Methods, Events, Superclasses 
>> clear G #% DESTRUCTOR NOT CALLED?? 
>> G = Generator(P) 
Generator instance deleted #% why is the destructor run now? 
G = 
    Generator handle 

    Properties: 
    plant: [1x1 Plant] 
    Methods, Events, Superclasses 
>> clear G 
Generator instance deleted #% and why is the destructor run properly now? 

私のデストラクタが毎回実行されることは非常に重要です。ここで何が起こっているのですか。デストラクタを適切に動作させるにはどうしたらいいですか? (私は完全にリスナーを削除し、これがうまくいかない場合は、直接GeneratorインスタンスからPlant.ListenerCallback()を呼び出すことができます。)

EDIT:私はclear Gを行う際に、変数Gは、ワークスペースから削除されたように見える - しかし、 GeneratorオブジェクトはP.Listener.Sourceに存在します。これは、デストラクタが呼び出されていない理由です。だから私はP.Listenerを削除することによって、Gを削除する方法がないと思います..これを私が欲しいものをするために得る方法はありますか?

+0

「削除G」を試してください。 「クリアG」ではなく「G」をクリアしますか?ドキュメントから「Figureや他のオブジェクトのハンドルをクリアすることはできますが、オブジェクト自体は削除されません」deleteを使用してオブジェクトやファイルを削除しても、そのオブジェクトを削除しても、ハンドル。" – tmpearce

+0

@tmpearce - それは動作します。私は 'clear G'を使うことを望んでいました。なぜなら、このコードははるかに大きなコードベースの一部であるからです。 MATLABを使っている人と仕事をするほとんどの人は、 'delete'と' clear'の違いが分からないので、これは本当に混乱するかもしれません。 –

+0

ええ、私は理解しています。デストラクタの問題ではなく、オブジェクトの 'clear'を使うので、この情報で質問を更新したいかもしれません。 – tmpearce

答えて

1

なぜこのような奇妙な時間にデストラクタが呼び出されましたか?

clear G #% DESTRUCTOR NOT CALLED?? 

P

G = Generator(P) 
Generator instance deleted #% why is the destructor run now? 

のリスナーでGへの参照が残っている新しいGeneratorがインスタンス化されると、リスナーが上書きされます。 Generatorの最初のインスタンスのデストラクタが呼び出されます。このインスタンスへの参照はなくなりました。

G = 
    Generator handle 

    Properties: 
    plant: [1x1 Plant] 
    Methods, Events, Superclasses 
>> clear G 
Generator instance deleted #% and why is the destructor run properly now? 

のは、前のステップで何が起こったのかもう一度見てみましょう:(1)plantのリスナーが新しいGeneratorで上書きされます。 (2)これは最初のGeneratorのデストラクタを呼び出します。 (3)デストラクタは、ワークスペース内のplant(!!!)(4)Gのリスナーを、新しいGeneratorの最後の残りのインスタンスにクリアします。したがって、clear Gはクラスデストラクタを呼び出します。あなたがclear代わりのdeleteを使用することができるようになるワンきれいではありません方法はclearコマンドに

function clear(varargin) 

%# check for Generator objects 
isGenerator = cellfun(@(x)evalin('caller','isa(x,''Generator'');'),varargin); 

%# I loop here b/c I don't have the time to carefully construct 
%# the evalin commands 
%# Generator gets deleted, everybody else gets cleared 
for i=1:nargin 
    if isGenerator(i) 
     evalin('caller',sprintf('delete %s',varargin{i})); 
    else 
     evalin('caller',sprintf('builtin(''clear'',''%s'');',varargin{i}); 
    end 
end 
+0

素晴らしい説明。醜いしかし簡単な回避策。いつものように感謝します。 –

1

をオーバーロードすることです


おそらく、私は2歳の質問を復活が、よ...

Matlabはデストラクタをクリアしたいと思っています。問題はリスナーをどのように定義したかにあります。

obj.plant.Listener = addlistener(obj, 'newSignal', ... 
       @(src, data) obj.plant.ListenerCallback(data)); 

このようにして、objへのハードコードされた参照を持つ無名関数を作成しました。 objが他の場所(例えば、ベースワークスペース内のクリアを介して)のスコープから外れると、objはあなたの無名関数に引き続き存在し続けます。代わりに、次のように定義した場合:

obj.plant.Listener = addlistener(obj, 'newSignal', ... 
      @(src, data) src.plant.ListenerCallback(data)); 

匿名関数にはハードコードされた参照がありません。リスナーコールバックの最初の引数は常に呼び出されたオブジェクトですが、無名関数でオブジェクト参照をハードコーディングするのではなく、その場で取得します。

これはあなたにとってまだ価値があると思っています。