Skip to content

Inheritance. A first insight

Inheritance1-UML
Inheritance 1 - UML

By talking about the class design we implicitly considered a point of view that merits a deeper view.

Indeed a good wide project requires more classes, and surely some of them can be derived from an ancestor.

A designer is so brought to create the parent class with some features to be necessarily inherited form every its child.
As always the UML class diagram helps us to visualize the design of class in a compact view.

In particular, while a member like a variable still remains the same, a method can be instead modified, and modified always with additions and never with subtractions.

To mark this choice, the virtual modifier is used at the end of a method  forward declaration.

Beware of this fact: we wrote definition only!

In freepascal the virtual modifier is required only for it.

Here the PrintMeVirtual function from Employee, whose job we'll explain immediately:

 

function PrintMeVirtual():string; virtual;   //I want that my children can declare this again

...

function TEmployee.PrintMeVirtual():string; //virtual NOT NEEDED HERE
var
    semployee :string;
begin
  semployee := '(Virtual print) Id : ' + inttostr(self.Id)  + '; Name : ' + self.Name  + '; Surname : ' + self.Surname + ' ';
  result := semployee + #13#10;
end;

As you can see the comment is clear: "virtual NOT NEEDED HERE".
But don't worry: in case of an error the compiler will warn you. It's just a syntax error.

Well... to be precise: virtual doesn't mean something that doesn't exist. This method works indeed.
It requires a redefinition by the children, to specialize this method, designed to work for the parent, and to be enriched from children according to their necessities.

What in case we don't redefine it?
No problem: child has this father's method working, but it will work exactly as written for the father, nothing more.
And this shows that virtual modifier doesn't force us to redefine a method, if we don't want.
[While to make it become a duty we have to add another modifier: matter for a future article]

This scenario is correct if we don't add nothing to redefine.
On the opposite is important to distinguish two possible situations. Think to define (and declare) in Worker a method called as the same in the code above: PrintMeVirtual.
How to know if it is an independent method, or the inherited one from Employee?

It's simple: to inherit, we have to add the override modifier. From the Worker class:

function PrintMeVirtual():string; override;

...

function TWorker.PrintMeVirtual():string;
begin
  result:= '(Virtual print) The selected worker has Id : ' + inttostr(self.Id) + ' ,name : ' + self.Name + ' , surname : ' + self.SurName + ' and working hours : ' + inttostr(self.WorkingHours) + #13#10;
end;

Again, the modifier is required only for forward declaration.
Without override we have just a normal function which has no connection with the homonym in the father class.