2012-04-08 80 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. 
相關問題