2014-07-21 83 views
-1

我可以通過聲明聲明一個類的類型:我可以傳遞一個泛型變量的類型作爲參數嗎?

type 
    TMyObject = class(TSomething); 
    TMyObjectClass = class of TMyObject; 

我試圖做這樣的事情:

IData<TIn,TOut> = interface; 
    IData = interface 
    function GetGenericData<Tin,TOut>: IData<TInput,TOut>; 
    function GetInType: TRttiType; 
    function GetOutType: TRttiType; 
    end; 

聲明一個基本類型,可以給訪問泛型類型和給我通用輸入和輸出類型的信息。

IData<TIn,TOut> = interface(IData) 
    ['{5B402458-22EC-4A8B-83F3-C11AC575B79E}'] 
    function GetInput(Index: Integer): TIn; 
    function GetInputCount: Integer; 
    function GetOutput(Index: Integer): TOut; 
    function GetOutputCount: Integer; 
    property Input[index: integer]: TIn read GetInput; 
    property Output[index: integer]: TOut read GetOutput; 
    property InputCount: integer read GetInputCount; 
    property OutputCount: integer read GetOutputCount; 
    end; 

這裏是實際的泛型類型,它包含2個數據數組。請注意,輸入和輸出不需要是相同的類型。

然後我有一個類包含一個或多個不同類型的IData

TStage = class(TPipelineStage, IData); 
TStage<TIn, TOut> = class(TStage, IData<TIn, TOut>); 

TMyPipeline = class 
    fStages = TArray<TStage>; <<-- this is really a list of TStage<?,?> 

我想在我的班級中列出不同的TStages,但顯然我無法對其編碼。
如何從fStages訪問TStage<IInterfaceA, InterfaceB>TStage<InterfaceB, InterfaceB>

我可以在此上下文中使用class of ....並從那裏實例化一個對象嗎?

我使用這種方法的原因是,我使用的管道階段的委託是這樣宣稱:

TDelegate<TIn, TOut> = reference to procedure(const Data: IData<TIn, TOut>); 
+0

'類的'站在類繼承之上。如果您想要混合使用數值類型和界面,則所有投注都將關閉。我甚至無法完全理解你想要做什麼。 –

+0

正如大衛所說,目前還不清楚你在努力達到什麼目的。從我在這裏可以看到你的代碼,也許你是在思考這個問題,並試圖拋出一切(泛型,接口和常規類)來試圖解決它?它看起來像你想要實現的可以使用常規類來完成,而不需要將接口和泛型添加到混合中,通過用自定義對象列表替換接口並讓多態處理其餘部分。你提到使用'Class Of'和對象實例化標誌着Factory模式的潛在用途。 –

回答

3

有在Delphi語言的限制,這將阻止你做的事情正是你正在嘗試的方式。取代碼:

IData<TIn,TOut> = interface; 
IData = interface 
    function GetGenericData<Tin,TOut>: IData<TInput,TOut>; 
    function GetInType: TRttiType; 
    function GetOutType: TRttiType; 
end; 

在這裏你有一個接口的通用方法。 Delphi(至少直到XE3)不支持接口中的通用方法。

在其他snipet您有:

TStage = class(TPipelineStage, IData); 
TStage<TIn, TOut> = class(TStage, IData<TIn, TOut>); 

TMyPipeline = class 
    fStages = TArray<TStage>; <<-- this is really a list of TStage<?,?> 

在代碼中的問題的答案是沒有。這是一個數組,而不是一個列表。但是,由於您的陣列持有TStage的實例,因此無論TInTOut的類型如何,它都將保留TStage<TIn, TOut>的實例,而不會造成任何問題。

您有這樣的疑問:

我想在我的課不同TStages的名單,但顯然我不能代碼。 如何從fStages訪問TStage和TStage?

其實你可以!可以聲明一個特定類型的列表(在你的情況下爲TStage)並保存降序類的實際實例,甚至是一個通用的子類。

在我看來,你想要一個通用的方法來返回TStage實例已經鍵入降序類型,以避免類型轉換和一些類型測試,最終返回nil如果階段是另一個類的實例, 對?

在這種情況下,泛型方法可能很有用,但只能在類中使用,而不能在接口中使用。我會做這樣的事情(我沒有德爾福在手來測試代碼,但這個想法似乎符合你的需求):

interface 

type 
    TMyPipeline = class 
    private 
    FStages: TObjectList<TStage>; 
    public 
    // Constructors, destructor and other methods... 
    function StageAs<TIn, TOut>(aIndex: Integer): TStage<TIn, TOut>; 
    end; 

implementation 

function TMyPipeline.StageAs<TIn, TOut>(aIndex: Integer): TStage<TIn, TOut>; 
var 
    stage: TStage; 
begin 
    stage := FStages[aIndex]; 
    if stage.InheritsFrom(TStage<TIn, TOut>) then 
    Result := TStage<TIn, TOut>(stage) 
    else 
    Result := nil; 
end; 
+1

'Delphi(至少直到XE3)不支持接口中的通用方法。「正確,即使在XE6中也不能編譯。事情是我想編寫接口而不是實現(按照尼克霍奇斯的建議),但這似乎是不可能的。 – Johan

+0

好的,你說的是,使用類而不是接口。 – Johan

+0

@Johan:正是! – AlexSC

相關問題