在泛型类型上调用方法?

7
为什么在Delphi (XE)中以下代码会产生错误?
unit UTest;

interface


type

TTest = class
  public
  procedure Foo<T>(A: T);
end;

implementation

{ TTest }

procedure TTest.Foo<T>(A: T);
begin
  A.Add('hej');
end;

end.

我认为在Delphi中的泛型类型是被插入到泛型函数中的,因此只有在使用不具有Add(string)方法的类型时才会出错。
1个回答

8
您的代码产生了编译错误,因为编译器无法知道 T 是否具有名为 Add 的方法并且接收一个字符串参数。
如果您正在使用Smalltalk或C ++模板,则您的假设是准确的。但是,泛型不同于模板。对于泛型,您需要将约束应用于类型参数。约束需要告诉编译器 T 必须具有哪些属性。
例如,您可以将 T 约束为派生自具有适当的 Add 方法的类。或者,您可以将 T 约束为实现具有适当的 Add 方法的接口。
Delphi通用约束文档链接: http://docwiki.embarcadero.com/RADStudio/en/Constraints_in_Generics 可以应用的通用约束相对较少,这有点可惜。例如,我很想能够限制一种类型具有某些数学运算符。例如,我希望能够限制一种类型具有+-运算符。但是,泛型和模板都有其优缺点,我认为这些限制是Delphi语言设计者所做出的合理设计决策的结果。

1
我想要做上述操作的原因是我有两个类,它们没有共同的基类(或接口),但某些方法签名完全相同。我猜这在有限的约束条件下不可能实现? - monoceres
2
没错。如果这些是模板,那么你就没问题了。但是对于泛型,你只能无可奈何了。你遇到了同样的问题,这也阻止了我编写既可以操作标量值又可以操作复数值的漂亮的数学算法。 - David Heffernan
1
太糟糕了:(我想我不得不退回到RTTI和if语句(呃)。 - monoceres
1
@monoceres 然后添加一个接口,其中包含“Add”方法的属性定义,将其用作对“T”的接口约束,并在两个类中实现该接口。请参见 https://bitbucket.org/jeroenp/besharp.net/commits/52b8721b5115724d51cdfae8bfed613028bdd285 - Jeroen Wiert Pluimers
1
这些类是从 WSDL(soap)自动生成的。我认为最好不要对它们进行任何操作。 - monoceres

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接