模板(或其他技术)是否支持以下构造?

时间:2010-10-23 18:15:45

标签: delphi templates generics language-features

这是我other question的后续行动。

当我第一次听到泛型时,就是在Delphi 2009发布之前(他们首先介绍了它)。我知道它之前在.Net中得到了支持,但我还没有挖掘那个领域。

阅读泛型,我了解到它允许类有一个变量参数,并且传递给它的任何值都将被替换为类的所有代码。

根据以下声明,描述了泛型的方式(或至少,我理解的泛型所允许的):

procedure TMyClass<T>.Init;
begin
  FField := T.Create(nil);
end;

我认为它会起作用。我假设编译失败的地方如下:

begin
  TMyClass<TComponent>.Create; //Works correctly
  TMyClass<TObject>.Create;  //Doesn't work, as even though it HAS a constructor, it has none that receive a single pointer parameter
  TMyClass<string>.Create; //Doesn't work, not an object. 
end;

现在,我知道我错了。所以,我现在想知道,是否有支持这种结构的技术/语言功能。代码模板也许?其他编程语言中的泛型?或者别的什么?

4 个答案:

答案 0 :(得分:1)

  

现在,我知道我错了。所以呢   我现在想知道,有没有   技术/语言功能   支持这样的结构。码   模板也许?其他的泛型   编程语言?或者可能   别的什么?

C#中的泛型具有您想要的强大功能。 C ++中的模板更强大 - 通过模板生成的代码与手工编写的代码相同,除了它们只能内联编译的部分,这很糟糕。

答案 1 :(得分:1)

@Gamecat,您不能将TObject作为约束,但您可以将class作为约束(这可以解决缺少TObject约束的问题。)

请注意,无论您使用的是TObject还是class,都无法通过参数调用Create而无需技巧。

示例1:class约束:

unit Unit1;

interface

uses
  Classes;

type
  TMyClass<T: class, constructor> = class
  strict private
    FField: T;
  public
    procedure Init;
  end;

implementation

procedure TMyClass<T>.Init;
begin
  FField := T.Create();
end;

end.

示例2:TComponent作为约束,Create

中的参数
unit Unit2;

interface

uses
  Classes;

type
  TMyClass<T: TComponent, constructor> = class
  strict private
    FField: T;
  public
    procedure Init;
  end;

implementation

procedure TMyClass<T>.Init;
var
  ComponentClass: TComponentClass;
begin
  ComponentClass := T;
  FField := ComponentClass.Create(nil);
end;

end.

class约束外,您还可以拥有记录约束。 有了这个,您需要Default来初始化字段:

unit Unit3;

interface

uses
  Classes;

type
  TMyClass<T: record> = class
  strict private
    FField: T;
  public
    procedure Init;
  end;

implementation

procedure TMyClass<T>.Init;
begin
  FField := Default(T);
end;

end.

希望能够对泛型和约束有所了解。

- 的Jeroen

答案 2 :(得分:0)

您可以将约束放在泛型类型上。如果要使用该类型的某些方面,则需要此选项。例如,一种方法。

如果要调用构造函数,则需要在类约束旁边给出consructor约束:

type
  TMyClass<T: TComponent, constructor> = class
    // ..
  end;

procedure TMyClass<T>.Init;
begin
  FField := T.Create(nil);
end;

不幸的是,TObject不是有效的约束。 (根据Delphi XE)。

  

现在,我知道我错了。所以,我现在想知道,是否有支持这种结构的技术/语言&gt;功能。代码模板也许?其他&gt;编程语言中的泛型?或者别的什么?   这可能有风险甚至毫无意义。如果在泛型上调用方法X并使用不支持方法X的类对其进行实例化,那么正确的行为是什么......

答案 3 :(得分:0)

@Ken:为了让你所要求的代码以真正的通用方式工作,你需要有一个统一的输入系统,它可以合并引用类型(类)和值类型(字符串,整数等)。 / p>

从历史上看,原生Delphi没有这样的打字系统(.NET有,Delphi Prism中的泛型支持它,就像C#和VB.NET一样)。

解决这个问题很困难; Allen Bauer gave it a shot implementing a Nullable type,他必须做一些严格的扭曲,以覆盖引用和值类型的方式仅实现Equals(=)和NotEquals(&lt;&gt;)运算符行为。

所以支持这些将是艰难的,但可能是可行的:

begin
  TMyClass<TComponent>.Create; //Works correctly
  TMyClass<TObject>.Create;  //Doesn't work, as even though it HAS a constructor, it has none that receive a single pointer parameter
  TMyClass<string>.Create; //Doesn't work, not an object.
end;

- 的Jeroen