我正在尝试为复合控件构建一个通用祖先。最初的想法是这样的:
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: Can't create new instance without CONSTRUCTOR constraint in type parameter declaration。然而,添加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;
有更清洁的解决方案吗?另外,有人可以向我解释为什么 classtype-constraint 不足以直接在类型参数上调用虚拟构造函数吗?