没有无参数构造函数的泛型

时间:2017-07-06 09:38:55

标签: delphi delphi-10.1-berlin

有人可以解释为什么在下面的代码中,class1List 要求class1有一个无参数构造函数,但class2list 要求class 2有一个无参数构造函数。< / p>

unit Unit11;

interface

uses
  System.Generics.Collections;

type
  class1 = class
  public
    constructor Create( const i : integer ); virtual;
  end;

  class1List<T : class1 > = class( TObjectList< T > )
  public
    function AddChild( const i : integer ) : T;
  end;

  class2 = class
  public
    constructor Create( const i : integer );
  end;

  class2List<T : class2 > = class( TObjectList< T > )
  public
    function AddChild( const i : integer ) : T;
  end;


implementation

{ class1List<T> }

function class1List<T>.AddChild(const i: integer): T;
begin
  Result := T.Create( i );
  inherited Add( Result );
end;

{ class2List<T> }

function class2List<T>.AddChild(const i: integer): T;
begin
  Result := T.Create( i );
  inherited Add( Result );
end;

{ class1 }

constructor class1.Create(const i: integer);
begin

end;

{ class2 }

constructor class2.Create(const i: integer);
begin

end;

end.

1 个答案:

答案 0 :(得分:4)

function class1List<T>.AddChild(const i: integer): T;
begin
  Result := T.Create( i );
  inherited Add( Result );
end;

class1的构造函数被声明为virtual。因此,编译器知道T.Create产生了一个T的实例,该实例的目标构造函数已被调用。因此编译器接受此代码。请注意,早期版本的编译器会拒绝此代码并强制您使用以下强制转换

Result := T(class1(T).Create( i ));

但是更新版本的编译器已经消除了对这种技巧的需求。

function class2List<T>.AddChild(const i: integer): T;
begin
  Result := T.Create( i );
  inherited Add( Result );
end;

class2的构造函数不是virtual,因此编译器知道是否要调用class2的构造函数,可能该类无法正确初始化。它准备从专用类型T调用无参数构造函数(如果存在),并在声明泛型类型时应用constructor约束。但是,该语言无法为接受参数的构造函数应用构造函数约束。

现在,您可以应用constructor约束,但这样做没有用。为了正确初始化实例,您需要使用参数调用构造函数。实际上,这意味着您应该使用第一种方法使用虚拟构造函数。

不要试图摆脱这个洞。这段代码将编译

Result := T(class2(T).Create( i ));

但可能不会做你想要的。这会调用class2的静态构造函数,这肯定不是你想要的。