Introducing (in this Chapter):
- Abstract methods
- The concept of a type
- The Polymorphism Pattern
- Part 6 Source Download
Example 6.4 Abstract methods
So, this is all very nice and slick, but havent we chosen our example rather carefully? Yes we have, in order to concentrate on the essential principles. But there are different circumstances that we should also be able to accommodate. For example, the overridden methods were all similar in the previous example. What happens if they are very different? Lets say our base class is called MyShape. As subclasses we have MyEllipse and MyRectangle. We want to create a Draw method. MyShape.Draw does not make any sense what does it draw, a rectangle or an ellipse? So although every MyShape subclass that we create needs to have a Draw method, we cant define Draw for the base class in the usual way.In a situation like this we can use an abstract method. This is a method that we declare as abstract in the superclass. Being abstract means that it does not have an implementation and so does not exist in the superclass. Each subclass then provides its own implementation.
Maybe its easier to understand if we work through an example. Well create a TMyShape class with an abstract Draw method and two subtypes, TMyEllipse and TMyRectangle. The subtypes will have concrete Draw methods to draw either an ellipse or a rectangle and so override the abstract declaration in the superclass. Overriding implies dynamic binding, and so the abstract declaration must also be made virtual.
Ex 6.4 step 1 Creating an abstract method
Start a new application. Add a second unit for the class definitions shown below.unit MyShapesU;We have a base class, TMyShape (lines 59), derived from TObject and two subclasses, TMyEllipse and TMyRectangle, derived from TMyShape (lines 1017). Each of these declares a method Draw which is a procedure.
interface
uses ExtCtrls;
type
TMyShape = class (TObject)
public
procedure Draw (AnImage: TImage; ABorder: integer) ; virtual; abstract;
end;
TMyEllipse = class (TMyShape)
public
procedure Draw (AnImage: TImage; ABorder: integer) ; override;
end;
TMyRectangle = class (TMyShape)
public
procedure Draw (AnImage: TImage; ABorder: integer) ; override;
end;
implementation
{ TMyEllipse }
procedure TMyEllipse.Draw(AnImage: TImage; ABorder: integer) ;
begin
AnImage.Canvas.Rectangle(0, 0, AnImage.Width, AnImage.Height) ;
AnImage.Canvas.Ellipse (ABorder, ABorder, AnImage.Width - ABorder, AnImage.Height - ABorder) ;
end;
{ TMyRectangle }
procedure TMyRectangle.Draw(AnImage: TImage; ABorder: integer) ;
begin
AnImage.Canvas.Rectangle(0, 0, AnImage.Width, AnImage.Height) ;
AnImage.Canvas.Rectangle (ABorder, ABorder, AnImage.Width - ABorder, AnImage.Height - ABorder) ;
end;
end
For TMyShape, method Draw is declared as virtual, so that it can be overridden dynamically by a subclass, and as abstract, which means that it does not have an implementation. Looking at its method signature given by the declaration, we see that the Draw method has two parameters, a TImage where the object must be drawn, and an integer value ABorder to specify how far from the edge of the TImage the object must be drawn. TImage is part of Delphis VCL and displays a graphical image on a form. For more information, consult Delphis online Help.
An implementation for Draw must be provided in every branch derived from TMyShape. Thus, in the implementation section there is an implementation for TMyEllipse.Draw and for TMyRectangle.Draw. Since TMyShape.Draw is abstract it has no implementation. Methods like TMyEllipse.Draw or TMyRectangle.Draw, which implement an abstract method, are often called concrete methods.
Here, TMyShape establishes a type (only the Draw method in this example) which is implemented in the subtypes TMyEllipse and TMyRectangle.


