1. Home
  2. Computing & Technology
  3. Delphi Programming

Introducing Type Inheritance - Delphi OOP Part 6 - Chapter 13

By , About.com Guide

OOP Chapter 13 Subsitution

Summary of early and late binding

Because of substitution, the programmer can assign MyFurniture to any of three types, TFurniture, TChair or TTable. So for correct operation, Delphi must decide which of the three methods to use while the program is running, not before. This requires late binding (run-time binding or dynamic binding). (Binding refers to the link established between the object and the method).
Delphi uses late binding when the virtual and override keywords are used in declaring the classes.

By default, Delphi uses early binding (compile-time or static binding). This establishes the link between an object and a method while the program is being compiled, before it runs. This means that Delphi cannot then invoke different methods depending on the type of object involved at run-time and so early binding is non-polymorphic.

Example 6.3 Evolution in a polymorphic program

To support the future evolution of a program, the coupling within the program should be kept low, particularly in those parts of a program that are subject to change.

This example illustrates how the reduced coupling in a polymorphic program facilitates future evolutionary growth. It also looks at combining inheritance for reuse and for polymorphic behaviour. We’ll suppose we need to introduce another level of specialisation into this program by subclassing TTable into TCoffeeTable and TKitchenTable. What changes must we make?

Ex 6.3 step 1 The additional subclasses

Start with the polymorphic version of the program and add the two new subclasses. To show the combination of inheritance for reuse (subclassing) with inheritance for polymorphism (subtyping), we have also changed the existing method definitions to invoke the immediate ancestor’s method through the inherited keyword.
unit FurnitureU;

interface

type
   TFurniture = class (TObject)
   public
     function GetKind: string; virtual;
   end;

   TChair = class (TFurniture)
   public
     function GetKind: string; override;
   end;

   TTable = class (TFurniture)
   public
     function GetKind: string; override;
   end;

   TCoffeeTable = class (TTable)
   public
     function GetKind : string; override;
   end;

   TKitchenTable = class (TTable)
   public
     function GetKind : string; override;
   end;

implementation

{ TFurniture }

function TFurniture.GetKind: string;
begin
   Result := 'Furniture';
end;

{ TChair }

function TChair.GetKind: string;
begin
   Result := 'A Chair, ' + inherited GetKind;
end;

{ TTable }

function TTable.GetKind: string;
begin
   Result := 'A Table, ' + inherited GetKind;
end;

{ TCoffeeTable }

function TCoffeeTable.GetKind: string;
begin
   Result := 'Coffee Table, ' + inherited GetKind;
end;

{ TKitchenTable }

function TKitchenTable.GetKind: string;
begin
   Result := 'Kitchen Table, ' + inherited GetKind;
end;

end.
Several different things are happening here. First we derive two new subclasses, TCoffeeTable and TKitchenTable from TTable, so adding another layer to the hierarchy. These each have their own GetKind method declared as override, which therefore override the GetKind method they would otherwise inherit from TTable. These subclasses can use any of the methods they inherit from higher up in the hierarchy, and can override any of the inherited methods dynamically by using the override keyword provided that the overridden method is either a virtual method or is itself an override method. GetKind overrides its ancestor’s method which in turn overrides it’s ancestor’s method.

We can override existing methods to whatever depth is needed. But what if we actually want to be able to use an ancestor’s method even though it has been overridden? This turns out to be quite easy: Delphi has the inherited keyword and this allows us to access the ancestor’s method. This is useful when we don’t want to replace the ancestral method, but need to extend it for the descendant. In this case, we override the ancestor’s method, inherit it to get its functionality and then add any code needed to extend it.

In summary, we replace an ancestral method by redeclaring the method in the subclass with exactly the same name and parameter list as in the superclass. If we want this to be polymorphic substitution using late binding, the root declaration of the method must be virtual with an override declaration each time it is subsequently redeclared lower down the hierarchy. Where we want to extend the ancestral method, we invoke it in the subclass method through the inherited keyword.

This is the theory, at any rate. We haven’t seen it in action yet. So let’s modify the driver program to incorporate these additional classes.

Explore Delphi Programming
About.com Special Features

Holiday Central

What to eat, where to go, fun things to do and how to save money on the perfect gifts. More >

Family Tech Center

Stay connected and entertained with reviews on tips on the latest HDTVs, cellphones and more. More >

  1. Home
  2. Computing & Technology
  3. Delphi Programming
  4. Coding Delphi Applications
  5. OOP in Delphi
  6. Free Online OOP Course
  7. Introducing Type Inheritance - Delphi OOP Part 6 - Chapter 13

©2009 About.com, a part of The New York Times Company.

All rights reserved.