2012-04-08 109 views
10

我想为泛型类定义类类型(类型别名)。我想这样做,以便单元b的用户可以在不使用单元a的情况下访问TMyType。 我有台这样的:是否有可能在Delphi中为泛型类创建类型别名

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.TMyNormallClass是b.TMyNormalClass,反之亦然 - 它们指的是同一个类)。

+0

难道不可能的'TMyType '所有用户从单元B指?在这种情况下,您的解决方法可能是可行的。 – 2012-04-08 11:15:02

+1

为什么不创建一个界面并将其暴露给用户? – whosrdaddy 2012-04-08 18:38:21

回答

10

这是 当前不是 可能为泛型类声明类类型。

查看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>”是不可能的,但是一个泛型类的副本是好的。

+0

嗨LU RD,非常抱歉,这个问题已经由Wharren编辑,他改变了它的含义。 我改回来了。 我想为泛型类型声明一个类型别名,而不是类类型。 我知道我的解决方法适用于限制。 – 2012-04-09 04:45:38

+1

好的,我明白了。但为了避免歧义,你应该将“type alias”改为[“'class reference'”](http://docwiki.embarcadero.com/RADStudio/en/Class_References)。 – 2012-04-09 08:23:28

+0

嗯,我正在寻找一个类的别名,而不是一个类的引用。 – 2012-04-09 08:26:08

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. 
相关问题