์ ํต์ ์ธ ๊ฐ์ณฌ์งํฅ ๊ณ์ธต๊ณผ ํจ๊ป, ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ปดํฌ๋ํธ๋ก ๋ถํฐ ํด๋์ค๋ฅผ ๋น๋ํ๋ ๋ ๋ค๋ฅธ ์ผ๋ฐ์ ์ธ ๋ฐฉ๋ฒ์ผ๋ก, ๊ฐ๋จํ ๋ถ๋ถํด๋์ค๋ฅผ ๊ฒฐํฉํ์ฌ ๋น๋ํ๋ ๊ฒ์ ๋๋ค. ์ค์นผ๋ผ ๋ฑ์ ์ธ์ด๋ฅผ ํตํด์, ๋ฏน์ค์ธ์ ๋ํ ๊ฐ๋ ๊ณผ ํน์ฑ์ ์ต์ํ ์ ์์ ๊ฒ์ด๋ฉฐ, ํจํด์ JavaScript ์ปค๋ฎค๋ํฐ์์๋ ์ด๋ ์ ๋์ ์ธ๊ธฐ๋ฅผ ์ป์์ต๋๋ค.
์๋ ์ฝ๋์์๋ TypeScript์์ mixin์ ๋ชจ๋ธ๋ง ๋ฐฉ์์ ๋ณด์ฌ์ค๋๋ค. ์ฝ๋๋ฅผ ๋ณธ ํ, ์๋ ๋ฐฉ์์ ์ดํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
// Disposable Mixin
class Disposable {
isDisposed: boolean;
dispose() {
this.isDisposed = true;
}
}
// Activatable Mixin
class Actiavatable {
isActive: boolean;
activate() {
this.isActive = true;
}
deactivate() {
this.isActive = false;
}
}
class SmartObject {
constructor() {
setInterval(() => console.log(this.isActive + " : " + this.isDisposed), 500);
}
interact() {
this.activate();
}
}
interface SmartObject extends Disposable, Activatable {}
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 => {
Object.defineProperty(derivedCtor.prototype, name, Object.getOwnPropertyDescriptor(baseCtor.prototype, name));
});
});
}์์ ์ฝ๋๋ mixin์ ์ํํ๋ ๋ ํด๋์ค๋ก ์์ํฉ๋๋ค. ๋ ํด๋์ค๋ ๊ฐ๊ฐ ๋ถ๋ถ์ ์ธ ๊ธฐ๋ฅ์ ์ง์ค๋์ด ์์์ ์ ์ ์์ต๋๋ค. ์ดํ์๋ ๋ ๊ธฐ๋ฅ์ ๋ชจ๋ ์ฌ์ฉํ์ฌ ์๋ก์ด ํด๋์ค๋ฅผ ๋ง๋ค๊ธฐ ์ํด ์ด๋ค์ ํผํฉ(mix)ํ ๊ฒ์
๋๋ค.
// 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 {
...
}
interface SmartObject extends Disposable, Activatable {}์ฒซ ๋ฒ์งธ ์ฌํญ์ SmartObject ํด๋์ค์์ Disposable๊ณผ Activatable์ ํ์ฅํ๋ ๋์ SmartObject ์ธํฐํ์ด์ค์์ ํ์ฅํ๋ค๋ ๊ฒ์
๋๋ค. Declaration merging์ผ๋ก ์ธํด SmartObject ์ธํฐํ์ด์ค๊ฐ SmartObject ํด๋์ค์ ํผํฉ๋ฉ๋๋ค.
ํด๋์ค๋ฅผ ์ธํฐํ์ด์ค๋ก ์ทจ๊ธํ๊ณ Disposable ๋ฐ Activatable ๋ค์์๋ ์ ํ ๋ง ๊ตฌํ์ด ์๋ SmartObject ์ ํ์ผ๋ก ํผํฉํฉ๋๋ค. ์ด๊ฒ์ ์ฐ๋ฆฌ๊ฐ ํด๋์ค์์ ๊ตฌํ์์ mixin์ ์ ๊ณตํด์ผ ํ๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. ๊ทธ ์ธ์๋ mixin์ ์ฌ์ฉ์ ํผํ ์ ์์ต๋๋ค.
๋ง์ง๋ง์ผ๋ก ํด๋์ค์ ๊ตฌํ์์, mixin์ ํผํฉ(mix)ํฉ๋๋ค.
applyMixins(SmartObject, [Disposable, Activatable]);๋ง์ง๋ง์ผ๋ก, ์ฐ๋ฆฌ๋ฅผ ์ํด mixin์ ์ํ ํ ๋์ฐ๋ฏธ ํจ์๋ฅผ ๋ง๋ญ๋๋ค. ๊ทธ๋ฌ๋ฉด ๊ฐ mixin์ ์์ฑ์ด ์คํ๋๊ณ mixin์ ๋์์ผ๋ก ๋ณต์ฌ๋์ด ๋
๋ฆฝํ ์์ฑ์ ๊ตฌํํฉ๋๋ค.
function applyMixins(derivedCtor: any, baseCtors: any[]) {
baseCtors.forEach(baseCtor => {
Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
Object.defineProperty(derivedCtor.prototype, name, Object.getOwnPropertyDescriptor(baseCtor.prototype, name));
});
});
}