德尔福XE : Can I call virtual constructors with parameters from a classtype-constrained generic type without resigning to hacks?

标签 delphi generics constructor polymorphism 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;

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

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

...
FControl1 := TControl(TControl1).Create(Self);
...

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

一个可能有效的技巧是通过 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;

有更清洁的解决方案吗?另外,有人可以向我解释为什么类类型约束不足以直接在类型参数上调用虚拟构造函数吗?

最佳答案

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

FControl1 := TControlClass(TControl1).Create(Self);

关于德尔福XE : Can I call virtual constructors with parameters from a classtype-constrained generic type without resigning to hacks?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9586626/

相关文章:

delphi - 我可以设置什么文件的创建/上次修改/上次访问?

c# - 从基类实例化派生类的通用工厂方法

JAVASCRIPT:Arrays 构造函数是否自动具有一个名为 arguments 的变量?

java - 为什么Java泛型不能用于静态方法?

c++ - 像 C::C(const C&&) 这样的构造函数我们怎么调用它?除了禁止从 const 移动外,还有其他用途吗?

java - 使用 Guice,如何注入(inject)父类(super class)的构造函数参数?

delphi - 如何正确释放 DragObject

Delphi (DataSnap) 我需要验证线程吗?

delphi - 要安装哪些更新才能达到最新版本的 Delphi 2007?

generics - 为什么泛型父类(super class)型声明不允许引用子类型对象?