oop – MATLAB – 当涉及侦听器时,对象析构函数不运行

我有两个班,工厂和发电机. Generator会创建一个向量,并通过工厂侦听的notify()进行广播. classdef如下.请注意,我没有包含实际的数据生成方法,因为它对我的问题无关紧要.

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实例,它直到我第二次创建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(),如果这不起作用的话.)

编辑:看起来当我清除G时,变量G从工作空间中删除 – 但Generator对象仍然存在于P.Listener.Source中.这就是没有调用析构函数的原因.所以我想没有办法通过删除G来摆脱P.Listener ..有没有办法让这个做我想要的或者我只是卡住了?

最佳答案
为什么析构函数会在如此奇怪的时刻被调用?

clear G #% DESTRUCTOR NOT CALLED??

在P的听众中仍然有对G的引用

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

在实例化新的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)工厂的监听器被新的Generator覆盖. (2)这将调用第一个Generator的析构函数. (3)析构函数清除工厂的监听器(!!!)(4)工作空间中的G现在是新生成器的最后剩余实例.因此,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

转载注明原文:oop – MATLAB – 当涉及侦听器时,对象析构函数不运行 - 代码日志