我想为泛型类定义类类型(类型别名)。我想这样做,因此单元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,反之亦然 - 它们指的是同一个类)
答案 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.