Delphi XE:我可以使用类类型约束泛型类型中的参数调用虚拟构造函数,而不必接受黑客攻击吗?
我正在尝试为复合控件构建一个通用祖先。最初的想法是这样的:Delphi XE:我可以使用类类型约束泛型类型中的参数调用虚拟构造函数,而不必接受黑客攻击吗?,delphi,generics,constructor,polymorphism,generic-constraints,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; TL
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;
…但它会在运行时导致访问冲突
一个可能工作的黑客通过RTTI调用构造函数,但我认为这是一个相当肮脏的解决方案。< /P> 另一种基本有效的方法是使用类类型变量作为中间变量:
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;
类型
TControlClass=TControl的类别;
构造函数TCompositeControl.Create(所有者:TComponent);
变量
立法会一题,,
lCtrlClass2:TControlClass;
开始
继承的创建(AOOwner);
lCtrlClass1:=TControl1;
FControl1:=lCtrlClass1.Create(Self);
lCtrlClass2:=TControl2;
FControl2:=lCtrlClass2.Create(Self);
结束;
有更清洁的解决方案吗?另外,有人能给我解释一下为什么classtype约束不足以直接调用类型参数上的虚拟构造函数吗?您的类型转换不好:
TControl(TControl1)。Create(Self)
。这告诉编译器TControl1
是TControl
的实例,但我们知道它不是实例。这是课堂参考资料。类型将其强制转换为类引用类型:
FControl1 := TControlClass(TControl1).Create(Self);
如果您的类使用没有参数的构造函数(如TObject),我建议您按照编译器的说明进行操作: “将构造函数约束添加到类型参数声明” 它应该是这样的:
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;
TCompositeControl如果有效,请告诉我们。另一种语法是
FControl1 := TControl1(TControl1.NewInstance); // get memory for object
FControl1.Create(self); // call type-specific constructor
FControl2 := TControl2(TControl2.NewInstance); // get memory for object
FControl2.Create(self); // call type-specific constructor
这在Delphi的Classes.pas::CreateComponent中使用
我只是无法决定哪种选择最不丑陋 似乎是最新的delphi版本(西雅图)不再发出此编译器错误。我遇到了与应用程序相同的问题,但只有在使用DelphiXe8编译时,而不是使用delphi SeattleArghl,是的。抢手货有道理。顺便问一下,您是否也知道为什么我不能将
FControl1
和FControl2
分别声明为TControl1
和TControl2
?如果我这样做,我会得到一个编译器错误E2010不兼容的类型:“TLabel”和“TControl”在单元的末尾。不知道。我没有要测试的Delphi版本。从这个问题中删减代码,并将其作为一个新问题发布,如果这里还没有关于它的问题。当然可以。奇怪的是,到目前为止,我还不能用比TComponent
-子体更简单的方法重现这个问题。。。无论如何,再次感谢你的原始答案!请重读这个问题。这特别是关于带参数的构造函数,而构造函数
约束不能与这些参数一起使用。