delphi 是否可以创建泛型类的类型别名

iqxoj9l9  于 2022-12-18  发布在  其他
关注(0)|答案(3)|浏览(175)

我想为一个泛型类定义一个类类型(类型别名),这样单元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.

我已经找到了一个可能的变通方案,但我不喜欢它,因为它可能会引入难以找到的bug:

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

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

ymdaylpp

ymdaylpp1#

目前还不能为泛型类声明类类型。
有关更多信息,请参见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>“的引用是不可能的,但泛型类的副本是可以的。

hfyxw5xn

hfyxw5xn2#

因为不可能为泛型类声明“类型别名”,所以这里有一个使用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.
6ie5vjzr

6ie5vjzr3#

type  
    TMyArrOfT<T> = array of T;  
    TMyIntegers = TMyArrOfT<integer>;  

procedure x;  
var  
   t4: TMyIntegers;  
begin  
   t4 := [1,3,5,7,11];   //...
   for var i:integer := Low(t4) to High(t4) do  
      Memo1.Lines.Add(t4[i].ToString);  
end;  

type
    TMyArrOfT<T> = array of T;
    TMyButtons  = TMyArrOfT<TButton>;

procedure TForm1.Button1Click(Sender: TObject);
var
   t4: TMyButtons;
begin
   t4                 := [Button1, Button1, Button1, Button1, Button1]; // ...
   for var i: integer := Low(t4) to High(t4) do
      Memo1.Lines.Add(t4[i].Caption );
 end;

相关问题