轉載 TypeScript基礎入門之Mixinsapp
與傳統的OO層次結構一塊兒,另外一種從可重用組件構建類的流行方法是經過組合更簡單的部分類來構建它們。
您可能熟悉Scala等語言的mixin或traits的概念,而且該模式在JavaScript社區中也已經普及。函數
在下面的代碼中,咱們將展現如何在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開始。
您能夠看到每一個人都專一於特定的活動或能力。
咱們稍後將它們混合在一塊兒,造成兩種功能的新類。this
// 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組合的類。
讓咱們更詳細地看一下它是如何作到的:spa
class SmartObject implements Disposable, Activatable {
您可能在上面注意到的第一件事是,咱們使用工具而不是使用擴展。
這將類視爲接口,而且僅使用Disposable和Activatable後面的類型而不是實現。
這意味着咱們必須在課堂上提供實現。
除此以外,這正是咱們想要經過使用mixins避免的。prototype
爲了知足這一要求,咱們爲來自mixin的成員建立了替身屬性及其類型。
這使編譯器知足這些成員在運行時可用。
這讓咱們仍然能夠得到mixins的好處,儘管有一些簿記開銷。code
// Disposable isDisposed: boolean = false; dispose: () => void; // Activatable isActive: boolean = false; activate: () => void; deactivate: () => void;
最後,咱們將mixin混合到類中,建立完整的實現。blog
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]; }); }); }