Примеси
Для построения иерархии объектов помимо традиционного объектно-ориентированного подхода существует другой популярный способ создания классов из переиспользуемых компонентов - это создание класса путем объединения более простых частичных классов. Возможно, вам знакома идея примесей по таким языкам как Scala. Такой подход так же стал популярен и в JavaScript.Пример примеси
В примере ниже показано, как можно смоделировать примеси в TypeScript. После кода будет рассказано как он работает.// Одноразовая примесь class Disposable { isDisposed: boolean; dispose() { this.isDisposed = true; } } // Активируемая примесь 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(); } // Одноразовый isDisposed: boolean = false; dispose: () => void; // Активируемый isActive: boolean = false; activate: () => void; deactivate: () => void; } applyMixins(SmartObject, [Disposable, Activatable]) var 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]; }) }); }
Как понимать этот пример
Пример кода начинается с двух классов, которые будут выступать в качестве примесей. Как вы заметили, каждый из классов сосредоточен на определенной функциональности или возможности. Далее мы объединим их вместе в форме нового класса с объединенной функциональностью.// Одноразовая примесь class Disposable { isDisposed: boolean; dispose() { this.isDisposed = true; } } // Активируемая примесь class Activatable { isActive: boolean; activate() { this.isActive = true; } deactivate() { this.isActive = false; } }
Далее создадим класс, который будет управлять объединением двух примесей:
class SmartObject implements Disposable, Activatable {
Для начала обратите внимание, что вместо 'extends' используется ключевое слово 'implements'. Это позволяет представить классы в качестве интерфейсов, и использовать только типы Disposable и Activatable, но не реализацию классов. Тем не менее реализацию частично нужно будет описать в новом классе.
Частичное описание реализации функций является обязательным требованием, в новом классе необходимо описать свойства и их типы, которые попадут в новый класс из частичных классов. Это требует компилятор, для того, чтобы эти члены были доступны во время выполнения.
// Одноразовая примесь isDisposed: boolean = false; dispose: () => void; // Активируемая примесьisActive: boolean = false; activate: () => void; deactivate: () => void;
И далее примеси объединяются в класс:
applyMixins(SmartObject, [Disposable, Activatable])
И наконец, создается вспомогательная функция, которая выполняет объединение. Эта функция скопирует каждое свойство примесей и его реализацию в результирующий класс.
function applyMixins(derivedCtor: any, baseCtors: any[]) {
baseCtors.forEach(baseCtor => {
Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
derivedCtor.prototype[name] = baseCtor.prototype[name];
})
});
}
Комментариев нет :
Отправить комментарий
Примечание. Отправлять комментарии могут только участники этого блога.