是否可以在Delphi中为泛型类创建类型别名

时间:2012-04-08 02:50:21

标签: delphi generics types alias declaration

我想为泛型类定义类类型(类型别名)。我想这样做,因此单元b的用户可以访问TMyType而无需使用单元a。 我有这样的单位:

unit a;
interface
type
  TMyNormalObject = class
    FData: Integer;
  end;
  TMyType<T> = class
    FData: <T>;
  end;
implementation
end.

unit b;
interface
type
  TMyNormalObject = a.TMyNormalObject;  // works
  TMyType<T> = a.TMyType<T>; // E2508 type parameters not allowed on this type
implementation
end.

我已经找到了一个我不喜欢的可能的解决方法,因为它可能很难找到错误:

TMyType<T> = class(a.TMyType<T>); 

这种方法的问题在于它引入了一个新的类类型,而a.TMyType实例不是b.TMyType(而a.TMyNormallClass是b.TMyNormalClass,反之亦然 - 它们指的是同一个类)

2 个答案:

答案 0 :(得分:11)

目前不可以声明泛型类的类类型。

有关详细信息,请参阅QC76605以下更新。

示例:

TMyClass<T> = class
end;
TMyClassClass<T> = class of TMyClass<T>; //E2508 type parameters not allowed on this type

显示的解决方法如下所示:

TMyIntClass = TMyType<Integer>;
TMyIntClassClass = Class of TMyIntClass;

但是如评论那样,这将破坏泛型的整个概念,因为该类必须为每个泛型实例化进行子类化。

这里还有一个关于生成泛型类型的专用子类的类似解决方法的链接:derive-from-specialized-generic-types。在这种情况下,它看起来像这样:

TMySpecialClass = Class(TMyType<Integer>);

更新:

RM提出的解决方法:

TMyType<T> = class(a.TMyType<T>);

可以使用以下方案实现类型安全:

unit Unita;
interface
type
  TMyType<T> = class
    Constructor Create;
  end;

implementation

uses
  Unitb;

constructor TMyType<T>.Create;
begin
  Inherited Create;
  //WriteLn( Self.QualifiedClassName,' ',Unitb.TMyType<T>.QualifiedClassName);
  Assert(Self.QualifiedClassName = Unitb.TMyType<T>.QualifiedClassName);
end;

end.

unit Unitb;

interface

uses Unita;

type
  TMyType<T> = class(Unita.TMyType<T>);
implementation
end.

Project Test;
{$APPTYPE CONSOLE}    
uses
  System.SysUtils,
  Unita in 'Unita.pas',
  Unitb in 'Unitb.pas';

var
  t1 : Unita.TMyType<Integer>;
  t2 : Unitb.TMyType<Integer>;
  t3 : TMyType<Integer>;    
begin
  try
    //t1 := Unita.TMyType<Integer>.Create;  //Exception EAssertionFailed !!
    t2 := Unitb.TMyType<Integer>.Create;
    t3 := TMyType<Integer>.Create;
    ReadLn;
  finally
    //t1.Free;
    t2.Free;
    t3.Free;
  end;
end.

创建泛型类时,将进行测试以检查创建的类是否从单元b中声明的类型派生。因此,检测到从单元a创建该类的所有尝试。

更新2:

为了清楚起见,对泛型类的引用“class of type<T>”是不可能的,但泛型类的副本很好。

答案 1 :(得分:0)

由于无法为泛型类声明“类型别名”,因此这是使用interface的解决方案。

unit UnitA;

interface  

Uses UnitB; 

type
  TMyType<T> = class(TInterfacedObject,ITMyType<T>)
    FData : T;
    Constructor Create( aV : T);
  end;

implementation

constructor TMyType<T>.Create( aV : T);
begin
  Inherited Create;
  FData := aV;
  WriteLn( Self.QualifiedClassName);
end;

end.

unit UnitB;

interface

type
  ITMyType<T> = Interface
  End;

implementation

end.

program Test;
{$APPTYPE CONSOLE}
uses
  UnitA in 'UnitA.pas',
  UnitB in 'UnitB.pas';

var
  it1 : ITMyType<Integer>;
begin
  it1:= TMyType<Integer>.Create(1);
  ReadLn;
end.