Introducing Type Inheritance - Delphi OOP Part 6 - Chapter 13By Zarko Gajic Summary of early and late bindingBecause 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 programTo 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 subclassesStart 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.
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. |
|