如何从父类调用子类构造函数?

时间:2016-12-05 08:30:30

标签: delphi delphi-10.1-berlin

有没有办法从父类调用子类的Create?下面是这个Duplicate方法,我希望调用子类的构造函数,以便底部的测试成功。

type

  IBla<T> = interface(IInvokable)
    ['{34E812BF-D021-422A-A051-A492F25534C4}']
    function GetIntFromIface(): Integer;
    function Duplicate(): IBla<T>;
  end;

  TClassA<T> = class(TInterfacedObject, IBla<T>)
  protected
    function GetInt(): Integer; virtual;
  public
    function GetIntFromIface(): Integer;
    function Duplicate(): IBla<T>;
  end;

  TClassB = class(TClassA<Integer>, IBla<Integer>)
  protected
    function GetInt(): Integer; override;
  end;

function TClassA<T>.Duplicate: IBla<T>;
begin
  Exit(TClassA<T>.Create());
end;

function TClassA<T>.GetInt: Integer;
begin
  Exit(1);
end;

function TClassA<T>.GetIntFromIface: Integer;
begin
  Exit(GetInt());
end;

function TClassB.GetInt: Integer;
begin
  Exit(2);
end;

procedure TestRandomStuff.Test123;
var
  o1, o2: IBla<Integer>;
begin
  o1 := TClassB.Create();
  o2 := o1.Duplicate();    
  Assert.AreEqual(o2.GetIntFromIface, 2);
end;

1 个答案:

答案 0 :(得分:0)

这似乎有效:

function TClassA<T>.Duplicate: IBla<T>;
begin
  //Exit(TClassA<T>.Create());
  Exit( ClassType.Create as TClassA<T> );
end;

微妙的是ClassType.Create将创建(在这种情况下)TClassB,并且原始创建TClassA&lt;整数&gt;编译器认为与TClassB不同,因此调用TClassA&lt; T&gt; .GetInt而不是TClassB.GetInt。

修改

但请注意,这会调用TObject中定义的构造函数,并且不会调用子类中定义的任何构造函数。 (感谢David H)

然而,这里也是克服这种限制的解决方案:

interface
type

  IBla<T> = interface(IInvokable)
    ['{34E812BF-D021-422A-A051-A492F25534C4}']
    function GetIntFromIface(): Integer;
    function Duplicate(): IBla<T>;
  end;

  TClassA<T> = class(TInterfacedObject, IBla<T>)
  protected
    function GetInt(): Integer; virtual;
  public
    constructor Create; virtual;
    function GetIntFromIface(): Integer;
    function Duplicate(): IBla<T>;
  end;

  //TClassB = class(TClassA<Integer>)
  TClassB = class(TClassA<Integer>, IBla<Integer>)
  protected
    function GetInt(): Integer; override;
  public
    constructor Create; override;
    function Duplicate(): IBla<Integer>;
  end;

procedure Test123;

implementation

constructor TClassA<T>.Create;
begin
  inherited Create;
end;

function TClassA<T>.Duplicate: IBla<T>;
begin
  Exit(TClassA<T>.Create());
end;

function TClassA<T>.GetInt: Integer;
begin
  Exit(1);
end;

function TClassA<T>.GetIntFromIface: Integer;
begin
  Exit(GetInt());
end;

constructor TClassB.Create;
begin
  inherited Create;
end;

function TClassB.Duplicate: IBla<Integer>;
begin
  Result := TClassB.Create;
end;

function TClassB.GetInt: Integer;
begin
  Exit(2);
end;

procedure Test123;
var
  o1, o2: IBla<Integer>;
begin
  o1 := TClassB.Create();
  o2 := o1.Duplicate();
  Assert( o2.GetIntFromIface = 2);
end;