Oop MATLAB-当涉及侦听器时,对象析构函数未运行
我有两门课,Oop MATLAB-当涉及侦听器时,对象析构函数未运行,oop,matlab,destructor,handle,Oop,Matlab,Destructor,Handle,我有两门课,Plant和GeneratorGenerator创建一个向量,并通过notify()进行广播,后者Plant监听。下面是classdef。请注意,我没有包括实际的数据生成方法,因为它与我的问题无关 classdef Plant < handle properties Listener end methods function ListenerCallback(obj, data) #% Per
Plant
和Generator
Generator
创建一个向量,并通过notify()
进行广播,后者Plant
监听。下面是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
我的析构函数每次运行都很重要。这里发生了什么,如何让析构函数正常工作?(如果这不起作用,我可能会完全删除侦听器,直接从生成器
实例调用Plant.ListenerCallback()
)
编辑:看起来,当我执行
清除G
时,变量G
将从工作区中删除-但生成器
对象仍保留在p.Listener.Source
中。这就是为什么没有调用析构函数。所以我想没有办法通过删除G
来摆脱P.Listener
。。有没有办法让这个函数实现我想要的功能,或者我只是被卡住了?为什么在如此奇怪的时间调用析构函数
clear G #% DESTRUCTOR NOT CALLED??
在p
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?
让我们再看看上一步中发生了什么:(1)新的生成器将覆盖plant
的侦听器。(2) 这将调用第一个生成器的析构函数。(3) 析构函数清除工作区中plant
(!!!)(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
也许我在重复一个2年前的问题,但是
Matlab希望调用clear上的析构函数;问题在于你如何定义你的听众。您将其定义为:
obj.plant.Listener = addlistener(obj, 'newSignal', ...
@(src, data) obj.plant.ListenerCallback(data));
在这样做的过程中,您创建了一个匿名函数,该函数具有对obj的硬编码引用。当obj在其他地方超出范围时(例如通过在基本工作区中清除),它仍然存在于匿名函数中。如果您改为定义:
obj.plant.Listener = addlistener(obj, 'newSignal', ...
@(src, data) src.plant.ListenerCallback(data));
匿名函数中没有硬编码引用。侦听器回调的第一个参数始终是从中调用它的对象,但是您可以动态获取它,而不是在匿名函数中硬编码对象引用
希望这对你还是有价值的 尝试删除G;清除G
而不是仅清除G
?从文档中,“您可以清除图形或其他对象的句柄,但这不会删除对象本身。使用“删除”删除对象和文件。删除对象不会删除用于存储其句柄的变量(如果有)。@tmpearce-确实有效。我只希望使用clearg
,因为这段代码是一个更大的代码库的一部分。与我一起工作的大多数使用MATLAB的人都不知道delete
和clear
之间有什么区别,所以这可能会让人很困惑。是的,我理解。您可能希望使用此信息更新您的问题,因为析构函数没有问题,而是对象上的clear
有问题。此外,请查看前一个问题以了解更多信息:@strictlyrude27:请参阅下面我编辑的答案。简短回答:这是一个很好的解释。丑陋但直截了当的解决方法。一如既往地感谢您,先生。对于类事件来说,这是一个很好的解决方案,但不幸的是,对于独立于类的计时器回调或串行事件来说,这不是一个很好的解决方案。
obj.plant.Listener = addlistener(obj, 'newSignal', ...
@(src, data) src.plant.ListenerCallback(data));