Skip to content

Latest commit

ย 

History

History
117 lines (90 loc) ยท 3.86 KB

File metadata and controls

117 lines (90 loc) ยท 3.86 KB

Mixin

์†Œ๊ฐœ(Introduction)

์ „ํ†ต์ ์ธ ๊ฐ์ณฌ์ง€ํ–ฅ ๊ณ„์ธต๊ณผ ํ•จ๊ป˜, ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ถ€ํ„ฐ ํด๋ž˜์Šค๋ฅผ ๋นŒ๋“œํ•˜๋Š” ๋˜ ๋‹ค๋ฅธ ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•์œผ๋กœ, ๊ฐ„๋‹จํ•œ ๋ถ€๋ถ„ํด๋ž˜์Šค๋ฅผ ๊ฒฐํ•ฉํ•˜์—ฌ ๋นŒ๋“œํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์Šค์นผ๋ผ ๋“ฑ์˜ ์–ธ์–ด๋ฅผ ํ†ตํ•ด์„œ, ๋ฏน์Šค์ธ์— ๋Œ€ํ•œ ๊ฐœ๋…๊ณผ ํŠน์„ฑ์€ ์ต์ˆ™ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋ฉฐ, ํŒจํ„ด์€ JavaScript ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ๋„ ์–ด๋А ์ •๋„์˜ ์ธ๊ธฐ๋ฅผ ์–ป์—ˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ์‹œ ์ฝ”๋“œ(Code Sample)

์•„๋ž˜ ์ฝ”๋“œ์—์„œ๋Š” 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));
        });
    });
}

์˜ˆ์‹œ ์•Œ์•„๋ณด๊ธฐ(Understanding the sample)

์˜ˆ์‹œ ์ฝ”๋“œ๋Š” 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));
        });
    });
}