Polymorphism and inheritance using class reference?

class, delphi, reference

Solution

Your code behaves the way it does because your constructors are not virtual. Which means that the compiler binds to them at compile time. Which therefore means that the runtime type cannot be taken into account and the code always calls `TParent.Create`.

In order to allow the program to bind using the runtime type, you need to use virtual methods and polymorphism. So you can solve your problem by using virtual constructors:

program Project1;

{$APPTYPE CONSOLE}

type
  TParent = class;
  TParentClass = class of TParent;

  TParent = class
  public
    ID: string;
    constructor Create; virtual;
  end;

  TChild1 = class(TParent)
  public
    constructor Create; override;
  end;

  TChild2 = class(TParent)
  public
    constructor Create; override;
  end;

constructor TParent.Create;
begin
  ID := 'Parent';
end;

constructor TChild1.Create;
begin
  ID := 'Child1';
end;

constructor TChild2.Create;
begin
  ID := 'Child2';
end;

procedure Test(ImplClass: TParentClass);
var
  ImplInstance: TParent;
begin
  ImplInstance := ImplClass.Create;
  WriteLn(ImplInstance.ID);
  ImplInstance.Free;
end;

begin
  Test(TParent);
  Test(TChild1);
  Test(TChild2);
  Readln;
end.

Output

Parent
Child1
Child2

A rule of thumb here is that whenever you use a meta-class to instantiate an object, your classes constructor should be virtual. This rule of thumb has exceptions, but I personally have never had to break this rule in my production code.

Problem

The output of the console application below is ``` Parent Parent Parent ``` instead of ``` Parent Child1 Child2 ``` Why would this happen ? Furthermore, how to get the intended output ? Many thanks ! PS: Still no clue after reading this related SO post ... ``` program Project1; {$APPTYPE CONSOLE} type TParent = class; TParentClass = class of TParent; TParent = class public ID: string; constructor Create; end; TChild1 = class(TParent) public constructor Create; end; TChild2 = class(TParent) public constructor Create; end; constructor TParent.Create; begin ID := 'Parent'; end; constructor TChild1.Create; begin ID := 'Child1'; end; constructor TChild2.Create; begin ID := 'Child2'; end; procedure Test(ImplClass: TParentClass); var ImplInstance: TParent; begin ImplInstance := ImplClass.Create; WriteLn(ImplInstance.ID); ImplInstance.Free; end; begin Test(TParent); Test(TChild1); Test(TChild2); Readln; end. ```

Original source

Related problems