【问题标题】:Polymorphism and inheritance using class reference?使用类引用的多态性和继承?
【发布时间】:2014-05-13 09:41:59
【问题描述】:

下面控制台应用程序的输出是

Parent
Parent
Parent

而不是

Parent
Child1
Child2

为什么会这样?此外,如何获得预期的输出?非常感谢!

PS: 看完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.

【问题讨论】:

  • 注意我编辑了代码。您并不是要在每个派生类中添加新的 ID 字段,以隐藏在 TParent 中声明的内容。

标签: class delphi reference


【解决方案1】:

您的代码的行为方式与它的行为方式相同,因为您的构造函数不是虚拟的。这意味着编译器在编译时绑定到它们。因此这意味着不能考虑运行时类型,代码总是调用TParent.Create

为了允许程序使用运行时类型进行绑定,需要使用虚方法和多态。所以你可以通过使用虚拟构造函数来解决你的问题:

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.

输出

家长 孩子1 孩子2

这里的经验法则是,每当您使用元类实例化对象时,您的类构造函数都应该是虚拟的。这个经验法则有例外,但我个人从来没有在我的生产代码中打破这个规则。

【讨论】:

  • 感谢您的及时和有益的回答!你能帮忙解释一下这个经验法则吗?当构造函数没有“显式使用”时,它们是否需要是虚拟的?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多