Destructors
A Destructor is a function that is called just before an Instance of a Class ceases to exist and is typically used to close files or release external resources associated with an Instance.
An Instance of a Class is destroyed when:
- The Instance is expunged using
⎕EXor)ERASE. - A function, in which the Instance is localised, exits.
But be aware that a destructor will also be called if:
- The Instance is re-assigned (see below)
- The result of
⎕NEWis not assigned (the instance gets created then immediately destroyed). - APL creates (and then destroys) a new Instance as a result of a reference to a member of an empty Instance. The destructor is called after APL has obtained the appropriate value from the instance and no longer needs it.
- The constructor function fails. The Instance is created before the constructor is run (inside it), and if the constructor fails, the fledgling Instance is discarded. This means a destructor might need to deal with a partially-constructed instance, so the code might need to check that resources were acquired before releasing them.
- On the execution of
)CLEAR,)LOAD,⎕LOAD,)OFFor⎕OFF.
Warning
A destructor may be executed on any thread.
An Instance of a Class only disappears when the last reference to it disappears. For example, the sequence:
I1←⎕NEW MyClass
I2←I1
)ERASE I1 will not cause the Instance of MyClass to disappear because it is still referenced by I2.
A Destructor is identified by the statement :Implements Destructor which must appear immediately after the function header in the Class script.
:Class Parrot
...
∇ kill
:Implements Destructor
'This Parrot is dead'
∇
...
:EndClass ⍝ Parrot pol←⎕NEW Parrot 'Scarlet Macaw'
)ERASE pol
This Parrot is dead Reassignment to pol causes the Instance referenced by pol to be destroyed and the Destructor invoked:
pol←⎕NEW Parrot 'Scarlet Macaw'
pol←⎕NEW Parrot 'Scarlet Macaw'
This Parrot is dead If a Class inherits from another Class, the Destructor in its Base Class is automatically called after the Destructor in the Class itself.
So, if we have a Class structure: DomesticParrot => Parrot => Bird containing the following Destructors:
:Class DomesticParrot: Parrot
...
∇ kill
:Implements Destructor
'This ',(⍕⎕THIS),' is dead'
∇
...
:EndClass ⍝ DomesticParrot
:Class Parrot: Bird
...
∇ kill
:Implements Destructor
'This Parrot is dead'
∇
...
:EndClass ⍝ Parrot
:Class Bird
...
∇ kill
:Implements Destructor
'This Bird is dead'
∇
...
:EndClass ⍝ Bird Destroying an Instance of DomesticParrot will run the Destructors in DomesticParrot, Parrot and Bird and in that order.
pol←⎕NEW DomesticParrot
)CLEAR
This Polly is dead
This Parrot is dead
This Bird is dead
clear ws