Constructors and Destructors
Didn't nobody seem to know me...
Everybody pass me by.
- Robert Johnson
Class Constructors
A constructor is a special method in a class that is executed automatically by the system when a new object of that class is being dynamically created. It is normally used to initialize all pertinent data and perform any sort of setup logic that is required for the class. The expectation is typically that the new object will be "ready to use" once the constructor has been executed.
The following rules apply to the definition and use of Constructor Methods.
♦ A constructor of a class is a method with the same name as the class. Due to method overloading, multiple constructors can be created for each class, each with a unique argument list. Constructors return nothing.
♦ For the purposes of the discussion below, a constructor with no method arguments will be referred to as the "default constructor" for that class.
♦ When an object is dynamically created using ‘new<>’, the appropriate constructor for the class is automatically executed. The compiler determines which constructor to be executed based on the argument list used in the 'new<>' call (e.g. new< MyClass(1,2) > ).
♦ Inside each constructor, the constructor for each of the base classes (listed in the 'from<>' keyword in the class statement) must also be called, if applicable. A base class constructor can be manually called from anywhere in the constructor, whether it has method arguments or not.
♦ If one of the constructors for a base class has no arguments (default constructor), it is not necessary to manually call the constructor method for that class from within the new class's constructor. The compiler automatically inserts the base class default constructor call, if any constructor from that class has not already been manually called. The VM will then automamtically call each default base class constructor that the compiler setup PRIOR to starting execution of the constructor itself.
♦ If a base class only has constructors with arguments, the base class constructor must be manually called from within the constructor. Of course, even if the base class has an empty constructor argument list, any one of the constructors can always be manually called, whether it has arguments or not.
♦ There is no rule that a class must have a constructor, but it is normally a good idea and generally considered good programming practice.
♦ There is a rule, however, that if any of the base classes has a constructor (even an empty argument list), then it is necessary to define at least one constructor, and that constructor must follow the rules described above relative to calling base class constructors.
♦ There is one single exception to this rule. The Base class (note "Base class" versus "base class") does have a default constructor, but a class derived directly from Base (which is the default) does NOT have to call the Base constructor - either manually or automatically. So a class derived only from Base does not need to need to define a constructor. The Base class constructor is provided primarily for completeness and setting a "good example", but it does not do anything. Since all classes are ultimately derived from Base, the alternative would be that every single class would have to define at least one constructor, which feels somewhat draconian. So this one exception with the "Base" class is supported by the compiler.
♦ Every class can also contain a special 'shared' constructor. The method must be marked as 'shared' and contain no arguments, and it is valid even if the class also has a "default constructor". The 'shared' keyword differentiates it from the default constructor. If one is defined, the VM invokes it automatically during startup of the Script/Application. It can be used to initialize shared data identifiers within the class and perform other one time initialization before an instance of the class is ever created.
The diagram below shows an example of a simple multiple inheritance class hierarchy.
NewClass is derived from ClassB and ClassC, each of which is derived from ClassA (which is allowed). If the NewClass constructor is called, and all other classes have default constructors which are setup for execution automatically by the compiler, the following constructor execution sequence will occur.
♦ The NewClass constructor is called automatically by the Virtual Machine.
♦ Before NewClass starts to execute, the ClassB constructor is executed automatically. In turn, before ClassB constructor is executed, the ClassA constructor is also executed automatically, and Base() after that.
♦ After the ClassB constructor has been executed, along with its entire hierarchy, the ClassC constructor is executed, with the same cascading effect as the ClassB constructor.
♦ Once ClassB and ClassC have been executed, the NewClass constructor is then executed.
Class Destructors
A destructor is a special method in a class that is executed automatically by the system when a dynamic object goes out scope. The Virtual Machine automamtically calls the destructor for every class in an object's hierarchy that has a destructor. The intent of the destructor is to provide an object the opportunity to perform cleanup internally before the object goes away. There is typically no need to perform memory cleanup, but there could be other types of script/application critical resources that are being maintained in the class, such as "SyncLock" or "FileStream" objects, that require some form of cleanup or state management before the object goes away
The following rules apply to the definition and use of Destructor methods.
♦ The destructor of a class is a special method with the name “Cleanup” appended to the name of the class, with no arguments and no return value. For example, “TestCleanup” would be the destructor for the “Test” class.
♦ A class does not need to define a Destructor method.
♦ When an object is no longer referenced, the destructor is automatically executed by the VM for each of the classes defined in the class hierarchy. The entire hierarchy is examined and only those that have destructors will be executed. This process will occur, even if the class itself does not have a destructor.
♦ If the object was created as ‘fore’, then each destructor is executed immediately when the object goes away and within the same thread.
♦ If the object was created as ‘back’, then each destructor is queued up to be executed in a separate destructor thread.
The "Aztec Class Definition" page describes foreground and background object cleanup in more detail, as well as more information regarding constructor definition and execution.