假设我有两个类a < matlab.mixin.Copyable
和b < handle
。
此处a
:
classdef a < matlab.mixin.Copyable
properties
hListener
end
methods
function obj = a(b)
obj.newListener(b);
end
function newListener(obj, b)
obj.hListener = addlistener(b, 'bEvent', @(o,e) disp('Received bEvent'));
end
function sobj = saveobj(obj)
sobj = copy(obj);
delete(sobj.hListener);
sobj.hListener = [];
end
end
end
和b
:
classdef b < handle
events
bEvent
end
methods
function obj = b
end
function raiseEvent(obj)
notify(obj, 'bEvent');
end
end
end
我在saveobj
中使用a
来保存时删除侦听器。我稍后加载类时会手动重新实例化一个监听器。
a
继承自matlab.mixin.Copyable
,因此我可以在copy
操作期间执行saveobj
- 这样我就可以复制原始对象并对其进行更改影响原始,然后将其保存到MAT文件。 (据说 - 这是我的问题所在。)
现在我在命令行运行以下命令:
>> bob = b; alice = a(bob);
>> bob.raiseEvent
Received bEvent
一切正常。现在,让我们保存:
>> save ab alice bob
并尝试再次举起活动:
>> bob.raiseEvent
% NOTHING HAPPENS!
原来听众已经走了!
>> alice.hListener
handle to deleted listener
这里发生了什么?为什么在listener
方法中sobj
和obj
之间共享了saveobj
个对象?
答案 0 :(得分:1)
在研究这个问题时,我发现了答案。我想我会在这些部分周围增加知识体系。
根据documentation for matlab.mixin.Copyable
,
调用表格的matlab.mixin.Copyable复制方法:
B = copy(A);
在以下条件下,产生描述的结果:
A
具有动态属性 -copy
不会复制动态属性。如果需要,您可以在子类中实现动态属性复制。
A
没有非依赖属性 -copy
创建一个没有属性值的新对象,而不调用类构造函数以避免引入副作用。
A
包含已删除的句柄 -copy
在输出数组中创建同一类的已删除句柄。
A
附加了听众 -copy
不会复制听众。 (强调添加)
A
包含枚举类的对象 - 枚举类不能继承matlab.mixin.Copyable
。
A
删除方法调用copy
-copy
创建合法副本,遵守适用于任何其他用法的所有行为。
我最初的意思是copy
调用会跳过一个值为侦听器句柄的属性。显然它的意思是,copy
不是完全跳过属性,而是引用原始的listener
对象,即它将句柄复制到监听器而不是监听器本身。
当然,当您load
复制的对象并且它具有对侦听器的引用时,它会抱怨:
Warning: Cannot load an object of class 'listener':
No matching constructor signature found.
Warning: During load:
An invalid default object has been detected while loading a heterogeneous array of
class event.listener. An empty array of class event.listener will be returned.
最简单的方法是修改saveobj
:
function sobj = saveobj(obj)
sobj = copy(obj);
sobj.hListener = [];
end
在这里,我没有在监听器上显式调用delete
,因为这会删除实际对象。相反,我只是清除对该对象的引用。