I have two classes, Plant
and Generator
. Generator
creates a vector and broadcasts it via notify()
, which Plant
listens for. The classdefs are below. Note that I didn't include the actual data-generation method because it's irrelevent to my question.
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
I noticed that the Generator
destructor behaves really oddly: the first time I create then delete a Generator
instance, it does not run the destructor until the second time I create the Generator
instance. Here's an example:
>> 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?
It's pretty important that my destructor runs every time. What is going on here, and how can I get the destructor to operate properly? (I might just remove the listener altogether and directly call Plant.ListenerCallback()
from the Generator
instance if this doesn't work out.)
EDIT: Looks like when I do clear G
, the variable G
is removed from the workspace - but the Generator
object lives on in P.Listener.Source
. This is why the destructor isn't being called. So I guess there's no way to get rid of P.Listener
by deleting G
.. is there any way to get this to do what I want or am I just stuck?
Perhaps I'm resurrecting a 2 year old question, but...
Matlab wants to call the destructor on clear; the problem is in how you've defined your listener. You defined it as:
In doing so, you've created an anonymous function that has a hardcoded reference to obj. When obj goes out of scope elsewhere (e.g. via clearing in the base workspace), it still continues to exist in your anonymous function. If you instead define:
there's no hardcoded references in the anonymous function. The first argument to the listener callback is always the object it was invoked from, but you get it on the fly rather than hardcoding an object reference in an anonymous function.
Hope this is still of some value to you!
Why is the destructor called at such weird times?
There is still a reference to
G
in the listener ofP
As the new
Generator
is instantiated, the listener gets overwritten. This calls the destructor of the first instance ofGenerator
, since there is no longer any reference to it.Let's look again what happened in the previous step: (1) The listener of
plant
gets overwritten with the newGenerator
. (2) This calls the destructor of the firstGenerator
. (3) The destructor clears the listener ofplant
(!!!) (4)G
in the workspace is now the last remaining instance of the newGenerator
. Thus,clear G
calls the class destructor.One not-pretty way that would allow you to use
clear
instead ofdelete
would be to overload theclear
command