Delphi XE:我是否可以使用classtype约束泛型类型的参数调用虚拟构造函数而不必重新签名?

Oli*_*sen 5 delphi generics polymorphism constructor generic-constraints

我正在尝试为复合控件构建一个通用的祖先.最初的想法看起来像这样:

type
  TCompositeControl<TControl1: TControl; TControl2: TControl> = class(TWinControl)
  private
    FControl1,
    FControl2: TControl;
  public
    constructor Create(AOwner: TComponent); override; 
  end;

  TLabelAndEdit = TCompositeControl<TLabel, TEdit>; // simple example for illustration only

constructor TCompositeControl<TControl1,TControl2>.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FControl1 := TControl1.Create(Self);
  FControl2 := TControl2.Create(Self);
end;
Run Code Online (Sandbox Code Playgroud)

您可能已经知道,这将触发编译器错误E2568:无法在类型参数声明中创建没有CONSTRUCTOR约束的新实例.constructor然而,添加约束并没有帮助,因为它意味着无参数构造函数.

转换模板以TControl使代码可编译:

...
FControl1 := TControl(TControl1).Create(Self);
...
Run Code Online (Sandbox Code Playgroud)

...但它会在运行时导致访问冲突.

一个可能有用的黑客是通过RTTI调用构造函数,但我认为这是一个相当脏的解决方案.

另一个基本上有效的黑客是使用类类型变量作为中间体:

type
  TControlClass = class of TControl;

constructor TCompositeControl<TControl1,TControl2>.Create(AOwner: TComponent);
var
  lCtrlClass1,
  lCtrlClass2: TControlClass;
begin
  inherited Create(AOwner);
  lCtrlClass1 := TControl1;
  FControl1 := lCtrlClass1.Create(Self);
  lCtrlClass2 := TControl2;
  FControl2 := lCtrlClass2.Create(Self);
end;
Run Code Online (Sandbox Code Playgroud)

有更清洁的解决方案吗?另外,有人可以向我解释为什么classtype-constraint不足以直接调用type参数上的虚构造函数吗?

Rob*_*edy 6

你的类型很糟糕:TControl(TControl1).Create(Self).这告诉编译器TControl1就是一个实例TControl,但我们知道,这不是一个实例.这是一个类引用.将其类型转换为类引用类型:

FControl1 := TControlClass(TControl1).Create(Self);
Run Code Online (Sandbox Code Playgroud)