2015-12-11 174 views
1

我有一個泛型類型,它將成爲事件系統中事件的基類。我們期望這些是單例,但它也是通用的,這樣子類可以在事件觸發時指定它們在回調中期望的參數的類型。在泛型Typescript類中實現單例

我有什麼看起來像這樣:

export interface IEvent { } 
export interfact IEventArg { } 

export abstract class Event<TEvent extends IEvent, TEventArg extends IEventArg> implements IMessageHandler { 

private static s_instance : any; 
private static s_isInitializing : boolean; 

constructor() { 
    if (!Event.s_isInitializing) 
     throw new Error ("Use the GetInstance method to get this class instance."); 
} 

public static GetInstance<TEvent extends IEvent, TEventArg extends IEventArg>(type: { new() : T; }) : TEvent { 
    if (!s_instance) { 
     s_isInitializing = true; 
     s_instance = new type(); 
     s_isInitializing = false; 
    } 

    return s_instance; 
} 
} 

export class SelectionEvent extends Event<SelectionEvent, EmptyEventArg> { 
... 
} 

var event = SelectionEvent.GetInstance(SelectionEvent); 

有在這裏有些東西我覺得奇怪,並沒有大多是因爲打字稿語言要求。 GetInstance的參數似乎是必需的,因爲var x = new TEvent()似乎不被TypeScript允許。空接口有助於實施可被接受爲通用類型的內容。

這裏似乎沒有工作的是靜態變量和泛型類型的組合。 GetInstance方法中的塊是我想要做的,但顯然它不能編譯。我還擔心靜態實例變量不會爲每個事件創建一次,而只是每個事件實例創建一次,並因此被覆蓋。

任何指導在這裏將不勝感激。

回答

1

在C#中,泛型類的每個實例(一組類型參數)都有自己的一組靜態成員。這意味着您可以編寫一個單例模式,其中您有一個實例爲Foo<int>,另一個爲Foo<string>,依此類推。這是可能的,因爲泛型是清單在運行時 - 運行時系統實際上知道什麼是泛型,並且可以爲每個類型實例化分配新對象。此外,類的靜態端可以引用該類的類型參數(這是運行時語義的結果)。

在TypeScript中,情況並非如此。每個類只有一個構造函數,泛型或其他。這意味着類的靜態端不能「查看」通用類型參數,因爲對於具有靜態成員y的任何類X<T>X.y只有一個運行時隙。

類的單例模式通常不適合TypeScript;見How to define Singleton in TypeScript。我想你有一些XY problem在這裏,所以我不能推薦任何具體的替代方案,沒有關於你的用例是什麼(可能發佈一個單獨的問題)的更多信息。

此外,你應該從來沒有在TypeScript中有空接口。類型進行比較結構上,所以任何兩個空的類型是兼容的,你可以分配任何東西到類型爲空接口的變量。

+0

好吧,這就是我所關心的。我想我可能有一個替代實現的想法,會嘗試,並可能發佈一個單獨的問題。謝謝! –

+0

對於具有不同名稱和類型參數的派生類(通用單例的)是否也適用?我會假設這是作爲獨立的類來處理派生的。因此,當有一個通用版本時,每次需要一個獨立的單例時,需要創建一個空的派生類,但可以重用通用單例代碼。並不是說只有好奇才能做到這一點。 – ntziolis