Is it possible to create a type alias to a generic class in Delphi

最后都变了- 提交于 2019-11-30 18:43:16
LU RD

It's currently not possible to declare a class type for a generic class.

See QC76605 for more information. Also the update below.

Example :

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

The workaround that is presented looks like this :

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

But as commented, that would defeat the whole idea of generics, since the class would have to be subclassed for every generic instantiation.

Here is also a link to a similar workaround on generating a specialized subclass of a generic type: derive-from-specialized-generic-types. In this case it would look like this :

TMySpecialClass = Class(TMyType<Integer>);

Update :

The workaround proposed by RM:

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

can be implemented with type safety using following scheme:

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.

When creating the generic class, a test is made to check that the created class is derived from the type declared in unit b. Thereby all attempts to create this class from unit a is detected.

Update 2:

Just to be clear, a reference to a generic class, "class of type<T>" is not possible, but a copy of a generic class is fine.

Since it is not possible to declare a "type alias" for a generic class, here is a solution using an 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.
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!