Last time we saw an introduction of what the OOP entails, with a quick look at its four main principles (encapsulation, abstraction, inheritance, polymorphism) and talking about the default mode to instantiate (create) an object from a class, designed or not by us, with the constructor.
So much concepts at once, indeed; and from now on we'll trying to make order in our heads.
By writing the TEmployee constructors we applied the polymorphism: because of the hierarchical system, every class in FreePascal automatically derives at least from the most abstract class, TObject, taking its default members like the constructor itself.
We don't want to exclude its usage from a TEmployee's object, so that we overload it with two new constructors: by overloading we simply make them the new default ones, but keeping the possibility to recall the TObject's one when required.
he instantiation occupies memory, and even if closing an application that memory is freed, nonetheless it's better to provide a method who does this efficiently.
Again, a default method is present and automatically inherited: it's so called destructor!
Here a difference with the constructors: the destructor is unique!
The one in TObject is defined as virtual: this modifier implies that every inheriting class should redefine a new destructor.
By choosing it we temporarily suspend the ancestor's destructor from usage, just because of our personalized needs, like resetting a counter to zero (as we'll see).
After our additions we recall the parent destructor with the command inherited, at the end of the code block.
[Note: this is of worth even for the constructors, or for any method who derives from an ancestor/father model]
Here some code, from TEmployee class:
type TEmployee = class //Employee is a CLASS and is child of TObject private //PRIVATE ZONE protected public //PUBLIC (Anyone can see this zone) //PUBLIC METHODS constructor Create(); overload; // Class Method constructor Create(Name_,Surname_ : string); overload; // Class Method //Destructor (can be only ONE) Destructor Destroy; override; //The Override must be specified since we are overriding the virtual TObject destroy method. //At the end of a destructor, you should call Inherited to invoke the parent destructor. ... //Class Method Destructor TEmployee.Destroy; //override; //not needed here !!! begin counter:=counter-1; showmessage('Employee with Id ' + inttostr(self.Id) + ', Name ' + self.Name + ', Surname ' + self.Surname + ' is deleted'); //Self->This in c++ inherited; // Always call the parent destructor after running your own code end;
Notice that the override modifier is necessary only after the destructor's definition, not after its declaration.
Let's see now another important difference.