长话短说:以下代码不能在 Delphi 10.1 Berlin(Update 2)中编译。
interface
uses
System.Classes, System.SysUtils;
type
TTest = class(TObject)
public
function BuildComponent<T: TComponent>(const AComponentString: String): T;
end;
TSomeComponent = class(TComponent)
public
constructor Create(AOwner: TComponent; const AString: String); reintroduce;
end;
implementation
{ TTest }
function TTest.BuildComponent<T>(const AComponentString: String): T;
begin
if T = TSomeComponent then
Result := TSomeComponent.Create(nil, AComponentString)
else
Result := T.Create(nil);
end;
{ TSomeComponent }
constructor TSomeComponent.Create(AOwner: TComponent; const AString: String);
begin
inherited Create(AOwner);
end;
编译器发出了几条错误消息:
E2015:运算符不适用于此操作数类型
在if T = TSomeComponent then
行和
E2010不兼容的类型 - 'T'和'TSomeComponent'
在Result := TSomeComponent.Create(nil, AComponentString)
行。
为了规避这些,我可以转发TClass(T)
(#1},如LU RD's answer here中所述(尽管有人说,这个错误已经在 XE6 )和T(TSomeComponent.Create(nil, AComponentString))
(#2)。虽然,我觉得使用显式类型转换感到不舒服。
还有更好的方法吗?编译器不应该认识到,T
属于TComponent
类型,因为我明确约束了它吗?
首先,我尝试声明泛型函数的实现,就像它的接口一样:
function TTest.BuildComponent<T: TComponent>(const AComponentString: String): T;
但最终出现了错误
E2029:',',';'或'&gt;'预期但':'发现
答案 0 :(得分:3)
这在我遇到的任何版本的Delphi中都无法编译。你需要做一些演员来说服编译器编译它:
function TTest.BuildComponent<T>(const AComponentString: String): T;
begin
if TClass(T) = TSomeComponent then
Result := T(TSomeComponent.Create(nil, AComponentString))
else
Result := T(TComponentClass(T).Create(nil));
end;
那就是说,我认为我可能更喜欢:
if TClass(T).InheritsFrom(TSomeComponent) then
代替那种平等测试。
即便如此,尝试将具有不同参数的新构造函数拼接到基于虚拟构造函数的类看起来对我来说也是一种灾难。