Inheritance and Polymorphism

17.1 Inheritance

type
  TAnimal = class
  protected
    FName: string;
  public
    constructor Create(const AName: string); virtual;
    function Speak: string; virtual;             // virtual: can be overridden
    function Describe: string;                   // static (non-virtual)
  end;

  TDog = class(TAnimal)
  public
    function Speak: string; override;
  end;

  TCat = class(TAnimal)
  public
    function Speak: string; override;
  end;

constructor TAnimal.Create(const AName: string);
begin
  inherited Create;
  FName := AName;
end;

function TAnimal.Speak: string; begin Result := '...'; end;
function TAnimal.Describe: string; begin Result := FName + ' says ' + Speak; end;   // polymorphic call
function TDog.Speak: string; begin Result := 'Woof'; end;
function TCat.Speak: string; begin Result := 'Meow'; end;

var Animals: TArray<TAnimal> := [TDog.Create('Rex'), TCat.Create('Tom')];
for var A in Animals do
begin
  Writeln(A.Describe);
  A.Free;
end;

17.2 Method Binding Directives

Virtual method table (VMT): faster calls Dynamic method table (DMT): smaller memory, slower calls Override a virtual/dynamic method No implementation (with virtual)

Hide an inherited virtual method intentionally (suppresses the warning)

Can't be overridden further (also on classes: TMyClass = class sealed) message WM_XXX Windows message handler

17.3 Abstract Classes and Type Checks

Creating an instance of a class with abstract methods gives a warning, and calling an abstract method raises EAbstractError.

type
  TShape = class abstract
  public
    function Area: Double; virtual; abstract;
  end;

  TCircle = class(TShape)
  private
    FRadius: Double;
  public
    constructor Create(R: Double);
    function Area: Double; override;
  end;

if Shape is TCircle then
  Writeln('Radius: ', (Shape as TCircle).Radius:0:2);   // checked cast (EInvalidCast if wrong)
var C := TCircle(Shape);                                 // unchecked hard cast (fast, unsafe)

17.4 Virtual Constructors and Destructors

Destructors must be override of Destroy (always call inherited last). Constructors can be virtual to work with class references (Module 16.4). Components use constructor Create(AOwner: TComponent); override;.