The use case in our example relates to the information printing of employees and workers objects.
As previously said, every new object is added into the EmployeeList which is indeed polymorphic by nature.
This aspect is fundamental to understand that the printing functions must be managed to get the correct behavior.
To complete the talk we now take a look to the events linked to the print buttons, that you can see in the GUI we show here (and in the first page).
Under the Memo Box we have three buttons.
Two have similar behavior.
Show All Employees and Show All Workers buttons call the functions PrintMe from Employee and Worker classes.
So two distinct function just with the same name.
They work independently, without any link between them.
The third is of interest.
It calls the virtual print function from Employee:
procedure TForm1.ButtonShowAlEmployeesVirtualClick(Sender: TObject); var i,imax:integer; begin memo.Clear; imax:=TEmployee.CountEmployees - 1; //INVOKE CLASS METHOD !!! for i:=0 to imax do begin Memo.Lines.Add(TEmployee(EmployeeList.Items[i]).PrintMeVirtual); //Print all the polymorphic array as TEmployee or TWorker //PrintMeVirtual has OVERRIDE. If you remove override it will print everything as TEmployee (same with normal print) end; end;
By analyzing the code we could think that this is the same as the normal print of an employee object: instead here is where inheritance makes the difference!
Because we don't specify anything else, every object is treated as an employee, not taking care if it's a worker too; so when the list is scanned with the for loop, only the employee nature of an object is considered.
But wait a minute! every object is surely an employee!
What will happen is that the virtual print of the employee object will be executed, in despite of the real object's nature: where a worker, the father's function is executed.
We kill two birds with one stone!
This reminds a hierarchy in some way: and that's indeed what we discover when we try to make the same on the Worker's side.
On the Gui a corresponding button doesn't exists: we're going to see why.
A possible code is (always in Main unit):
procedure TForm1.ButtonShowAllWorkersAsEmployeesVirtualClick(Sender: TObject); var i,imax:integer; begin memo.Clear; imax:=TEmployee.CountEmployees - 1; //INVOKE CLASS METHOD !!! for i:=0 to imax do begin if TEmployee(EmployeeList.Items[i]) is TWorker then begin Memo.Lines.Add( (TWorker(EmployeeList.Items[i]) as TEmployee).PrintMeVirtual ); //Stamp all the polymorfic array as TEmployee or TWorker //PrintMeVirtual has OVERRIDE If you remove override will print everything like TEmployee (same with print) end; end; end;
Here the situation brings to a different results.
First of all we see that a hierarchy is confirmed: there is the necessity to look for the worker object's nature with the keyword is, which tests if an object belongs to a particular class; so... is TWorker? yes?
Then we cast the worker to the employee's nature, granting that the worker's overridden printing method will be used instead of the parent's virtual one.
This is the point: we need a casting to perform the operation.
But here the difference: we print only workers informations.
Every object which is only an employee will be skipped!
In other words, the behavior will be the same with the normal workers printing function.
That's why this event (with its forward declaration) is commented inside the Main unit code, and why the GUI has no button for it.