2010-08-06 59 views
4

我不確定在Delphi中這是否可行。我環顧四周,似乎無法找到答案(示例或無法行動,這是不可能的):爲通用對象列表創建對象

我有一個泛型列表類,我想創建一個泛型類型的實例。例如:

type 
    TTypeA = class(TObject); 

procedure Test; 
var 
    MyList: TobjectList<TTypeA>; 
    NewListObject: TTypeA; 
begin 
    MyList := TObjectList<TTypeA>.Create; 
    NewListObject := MyList.xxx //what to put on the xxx 
end; 

是否可以創建一個函數xxx來創建TTypeA類型的新對象?

@jeroen:謝謝你的回答。但是,我忘了我的問題中的一個重要細節:

我希望此代碼也適用於任何其他類型,所以如果沒有關於TObjectList類型T的事先知識。我可能會創建以下列表:

MyList: TObjectList<TCar>; 
MyList: TObjectList<TBike>; 

不知道如果MYLIST包含TCAR或TBike(從同一個基類和平等的構造都產生)我想一個新的項目添加到MYLIST。

,並與來自烏維·拉貝的建議,我碰到了一個問題:

我修改了我的班

TMyObjectList<T:class, constructor> = class(TMyBaseObjectList<T>)

其中TMyBaseObjectList被定義爲

TMyBaseObjectList<T:TMyBaseObject> = class(TObjectList)

現在我收到一個錯誤: 類型參數'T'不兼容le與類型'T:TMyBaseObject'

回答

3

正如你所知道的類型,你爲什麼不只是寫

NewListObject := TTypeA.Create; 
MyList.Add(NewListObject); 

這將是自然的方式在這裏做。 (我剛剛通過Jeroen的類似答覆得到通知)

如果您希望容器創建對象,則必須創建一個後裔類,該類更多地瞭解用於創建實例的泛型類型。構造函數約束條件可能對此有所幫助。

type 
    TMyObjectList<T:class, constructor> = class(TObjectList<T>) 
    public 
    function NewObject: T; 
    end; 

function TMyObjectList<T>.NewObject: T; 
begin 
    result := T.Create; 
end; 

注:當實際類型有一個名爲參數的構造函數,此功能才能創建

更新:這將有助於

TMyObjectList<T:constructor, TMyBaseObject> = class(TObjectList<T>) 
    public 
    function NewObj: T; 
    end; 
0

xxx處,輸入:TTypeA.Create(...);其中...是創建構造函數的參數。

0

我的猜測是,這是不可能的。當然,除非你在你的列表中的項目,在這種情況下,你可以這樣做:

NewListObject := MyList[0].ClassType.NewInstance as TTypeA; 
+0

直接調用NewInstance的壞主意。它不調用構造函數。 – 2010-08-06 13:27:29

+0

我沒有意識到這一點,謝謝指出。無論如何,Uwes的答案看起來像是最好的解決方案。 – 2010-08-06 14:43:40

0

或者,你可以從TCollectionItem下降從TCollection您的列表類和你的項目,並利用這些作爲基類。它們都是用所有的管道建成的。要使用你的例子:

type 
    TTypeA = class(TCollectionItem); 

procedure Test; 
var 
    MyList: TCollection; 
    NewListObject: TTypeA; 

begin 
    MyList := TCollection.Create(TTypeA); 
    NewListObject := MyList.Add; 
end; 

編輯:我知道,它不使用泛型,但你可以看看TCollection和TCollectionItem更多的設計思路,特別是當它涉及到處理所有權,通知和生命週期管理。

0

據我所知,只能在泛型類的泛型類中使用無參數構造函數。

解決此問題的一個「解決方法」是使用匿名方法創建對象,但這意味着您需要創建許多方法。

至於其他問題...

TMyObjectList<T:class, constructor> = class(TMyBaseObjectList<T>) 
TMyBaseObjectList<T:TMyBaseObject> = class(TObjectList) 

我相信正確的申報將

TMyObjectList<T:TMyBaseObject, constructor> = class(TMyBaseObjectList<T>) 
TMyBaseObjectList<T:TMyBaseObject> = class(TObjectList) 

TMyBaseObjectList已經強制噸至是類型TMyBaseObject的。如果你在TMyObjectList中聲明瞭T:class,它將不會滿足TMyBaseObjectList的要求。