type
TForm72 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
TTestForm = class(TForm)
public
constructor CreateTest(AOwner: TComponent); virtual;
end;
TTestForm1 = class(TTestForm)
public
constructor CreateTest(AOwner: TComponent); override;
end;
TTest<T: TTestForm, constructor> = class(TObject)
public
class procedure Test;
end;
var
Form72: TForm72;
implementation
{$R *.dfm}
procedure TForm72.FormCreate(Sender: TObject);
begin
TTest<TTestForm1>.Test;
end;
{ TTest<T> }
class procedure TTest<T>.Test;
var
F: T;
begin
F := T.CreateTest(Application);
Form72.Caption := F.Name;
end;
{ TTestForm }
constructor TTestForm.CreateTest(AOwner: TComponent);
begin
inherited Create(AOwner);
end;
{ TTestForm1 }
constructor TTestForm1.CreateTest(AOwner: TComponent);
begin
inherited;
Caption := 'Bang';
end;
end.
此代码在XE2中编译,但失败并出现“[dcc32错误] Unit71.pas(55):E2010不兼容的类型:XE3中的'T'和'过程,无类型指针或无类型参数'”。我做错了什么,还是编译错了?
答案 0 :(得分:4)
实际上,此代码突出显示了XE2中的编译器错误。在XE2中,代码在不应该编译时编译。删除constructor
约束,编译失败并显示
E2568 Can't create new instance without CONSTRUCTOR constraint in type parameter declaration
但constructor
约束仅表明该类具有无参数构造函数。 documentation州:
构造函数约束
类型参数可以由零或一个实例约束 保留字“构造函数”。这意味着实际的参数类型 必须是一个定义默认构造函数的类(public 无参数构造函数),使泛型类型中的方法 可以使用参数类型构造参数类型的实例 默认构造函数,不知道有关参数类型的任何信息 本身(没有最低基本类型要求)。
constructor
约束的存在或其他因素影响此代码的事实表明XE2编译器有错误。
在XE3中,代码无法正确编译。使用语法T.Create
调用构造函数的唯一方法是使用constructor
约束并调用无参数构造函数。这不是这种情况,因此XE3正确报告编译错误。
你需要一些演员才能进行编译。
F := T(TTestForm(T).CreateTest(Application));
这是一个well-known trick来解决Delphi泛型实现处理构造函数的一些怪癖。虽然看起来很乱,但我相信这段代码是语言设计者打算使用的。在我看来,行为的改变是由于错误修复而XE3的行为与设计相符。