Constructors and destructors
Contents
Constructors and destructors#
When you create an instance of a class using ⎕NEW BaseClass
, you may want to supply some parameters. For this, we use a special type of method (function) called a constructor.
Constructors#
When you create a new instance, a constructor (if one exists in the class script) will be called.
]dinput
:Class cl1
∇ Ctor
:Access public
:Implements constructor
⎕←'Hi!'
∇
:EndClass
inst←⎕NEW cl1
Hi!
We defined a tradfn called Ctor
(it could be called anything, though) and declared it available from the outside (it must be, as you can’t be inside yet when you’re just creating the instance). As you saw, creating an instance with ⎕NEW
ran the constructor.
Here’s a slightly modified version where the constructor sets a field value:
]dinput
:Class cl2
:Field public value
∇ Ctor x
:Access public
:Implements constructor
value←x
∇
:EndClass
Here we have an uninitialised field (value
) and a monadic constructor (Ctor
) which sets the field upon construction:
inst←⎕NEW cl2 42
inst.value
42
A class can have multiple constructors, too:
]dinput
:Class cl3
∇ None
:Access public
:Implements constructor
⎕←'No arguments.'
∇
∇ One x
:Access public
:Implements constructor
⎕←'1 argument:'x
∇
:EndClass
Here is a class with two constructors. APL will call the appropriate one (niladic or monadic):
instA←⎕NEW cl3 42
instB←⎕NEW cl3
┌───────────┬──┐ │1 argument:│42│ └───────────┴──┘
No arguments.
Or why not a class with three constructors:
]dinput
:Class cl4
∇ None
:Access public
:Implements constructor
⎕←'No arguments.'
∇
∇ One x
:Access public
:Implements constructor
⎕←'1 argument:'x
∇
∇ Two(a b)
:Access public
:Implements constructor
⎕←'2 arguments'a b
∇
:EndClass
instA←⎕NEW cl4
instB←⎕NEW cl4 42
instC←⎕NEW cl4 (42 3.1415)
No arguments.
┌───────────┬──┐ │1 argument:│42│ └───────────┴──┘
┌───────────┬──┬──────┐ │2 arguments│42│3.1415│ └───────────┴──┴──────┘
So APL calls the right constructor based on the number of arguments (if you’ve provided several). Another approach is to make a fancy constructor that handles everything:
]dinput
:Class cl5
:Field public name←'baby'
:Field public age←0
∇ Ctor x
:Access public
:Implements constructor
:If ' '=⊃0⍴x
name←x
:Else
age←x
:EndIf
∇
:EndClass
instA←⎕NEW cl5 42
instA.(name age)
instB←⎕NEW cl5 'Charlie'
instB.(name age)
┌────┬──┐ │baby│42│ └────┴──┘
┌───────┬─┐ │Charlie│0│ └───────┴─┘
One final example of multiple constructors:
]dinput
:Class cl6
∇ None
:Access public
:Implements constructor
⎕←'No arguments.'
∇
∇ One x
:Access public
:Implements constructor
⎕←'1 argument:'x
∇
∇ Two(a b)
:Access public
:Implements constructor
⎕←'2 arguments'a b
∇
∇ Three(a b c)
:Access public
:Implements constructor
⎕←'3 arguments:'a b c
∇
:EndClass
We have 0–3. What happens when I call this with more than 3? Let’s see, shall we?
instA←⎕NEW cl6
instB←⎕NEW cl6 42
instC←⎕NEW cl6 (2.7 3.1 42)
instD←⎕NEW cl6 (1 2 3 4 5 6 7)
No arguments.
┌───────────┬──┐ │1 argument:│42│ └───────────┴──┘
┌────────────┬───┬───┬──┐ │3 arguments:│2.7│3.1│42│ └────────────┴───┴───┴──┘
┌───────────┬─────────────┐ │1 argument:│1 2 3 4 5 6 7│ └───────────┴─────────────┘
In other words, APL tries to match the specific number of arguments, but if there is no exact match, it passes the array as a single argument to the constructor that takes one argument.
Destructors#
Sometimes when an instance ceases to exist, you want to do some clean-up. For example, when a webserver is closed, you might want to free ports and write a message to the log, etc. This functionality is handled by a destructor.
]dinput
:Class cl7
∇ Hi
:Access public
:Implements constructor
⎕←'Hello there!'
∇
∇ Bye
:Implements destructor
⎕←'See you later!'
∇
:EndClass
inst←⎕NEW cl7
2+3 ⍝ do some work
⎕EX 'inst' ⍝ Expunge
2×3
Hello there!
5
See you later!
6