TypeScript基礎入門之Mixins
介紹
與傳統的OO層次結構一起,另一種從可重用元件構建類的流行方法是通過組合更簡單的部分類來構建它們。
您可能熟悉Scala等語言的mixin或traits的概念,並且該模式在JavaScript社群中也已經普及。
Mixin示例
在下面的程式碼中,我們將展示如何在TypeScript中對mixin進行建模。
在程式碼之後,我們將分解其工作原理。
// Disposable Mixin class Disposable { isDisposed: boolean; dispose() { this.isDisposed = true; } } // Activatable Mixin class Activatable { isActive: boolean; activate() { this.isActive = true; } deactivate() { this.isActive = false; } } class SmartObject implements Disposable, Activatable { constructor() { setInterval(() => console.log(this.isActive + " : " + this.isDisposed), 500); } interact() { this.activate(); } // Disposable isDisposed: boolean = false; dispose: () => void; // Activatable isActive: boolean = false; activate: () => void; deactivate: () => void; } applyMixins(SmartObject, [Disposable, Activatable]); let smartObj = new SmartObject(); setTimeout(() => smartObj.interact(), 1000); //////////////////////////////////////// // In your runtime library somewhere //////////////////////////////////////// function applyMixins(derivedCtor: any, baseCtors: any[]) { baseCtors.forEach(baseCtor => { Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => { derivedCtor.prototype[name] = baseCtor.prototype[name]; }); }); }
理解示例
程式碼示例以兩個類作為我們的mixins開始。
您可以看到每個人都專注於特定的活動或能力。
我們稍後將它們混合在一起,形成兩種功能的新類。
// Disposable Mixin class Disposable { isDisposed: boolean; dispose() { this.isDisposed = true; } } // Activatable Mixin class Activatable { isActive: boolean; activate() { this.isActive = true; } deactivate() { this.isActive = false; } }
接下來,我們將建立將處理兩個mixin組合的類。
讓我們更詳細地看一下它是如何做到的:
class SmartObject implements Disposable, Activatable {
您可能在上面注意到的第一件事是,我們使用工具而不是使用擴充套件。
這將類視為介面,並且僅使用Disposable和Activatable後面的型別而不是實現。
這意味著我們必須在課堂上提供實現。
除此之外,這正是我們想要通過使用mixins避免的。
為了滿足這一要求,我們為來自mixin的成員建立了替身屬性及其型別。
這使編譯器滿足這些成員在執行時可用。
這讓我們仍然可以獲得mixins的好處,儘管有一些簿記開銷。
// Disposable isDisposed: boolean = false; dispose: () => void; // Activatable isActive: boolean = false; activate: () => void; deactivate: () => void;
最後,我們將mixin混合到類中,建立完整的實現。
applyMixins(SmartObject, [Disposable, Activatable]);
最後,我們建立了一個輔助函式,它將為我們進行混合。
這將貫穿每個mixin的屬性並將它們複製到mixins的目標,並使用它們的實現填充替代屬性。
function applyMixins(derivedCtor: any, baseCtors: any[]) { baseCtors.forEach(baseCtor => { Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => { derivedCtor.prototype[name] = baseCtor.prototype[name]; }); }); }