Миксины

Последнее обновление: 18.05.2021

TypeScript, как и многие объектно-ориентированные языки, как, например, Java или C#, не позволяет использовать напрямую множественное наследование. Мы можем реализовать множество интерфейсов в классе, но унаследовать его можем только от одного класса. Однако функциональность миксинов (mixins) частично позволяют унаследовать свойства и методы сразу двух и более классов.

Рассмотрим на примере. Пусть, у нас есть класс Animal, который представляет животное, и класс Movable, который представляет транспортное средство. Оба эти класса имеют свой уникальный функционал, который позволяет выполнять заложенные в них задачи. И также пусть у нас будет класс, который представляет лошадь - с одной стороны, лошадь является животным и наследует все черты, присущие животному, а с другой стороны, лошадь также можно использовать в качестве транспортного средства. То есть для создания подобного класса было бы неплохо унаследовать его сразу и от класса Animal, и от класса Movable. Решим эту задачу на языке TypeScript:

class Animal {
 
    feed():void {
        console.log("Кормим животное");
    }
}
 
class Movable {
 
    speed: number=0;
    move(): void {
		console.log("Перемещаемся");
    }
}
 
class Horse {}

interface Horse extends Animal, Movable {}
 
function applyMixins(derivedCtor: any, baseCtors: any[]) {
    baseCtors.forEach(baseCtor => {
        Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
            derivedCtor.prototype[name] = baseCtor.prototype[name];
        });
    });
}
 
applyMixins(Horse, [Animal, Movable]);
 
let pony: Horse = new Horse();
pony.feed();
pony.move();

Чтобы класс Horse мог унаследовать методы классов Animal и Movable, определяется одноименный интерфейс Horse, который расширяет интерфейсы Animal и Movable:

interface Horse extends Animal, Movable {}

Но чтобы миксин мог унаследовать функционал, этого недостаточно. Нам еще надо использовать специальную функцию, которая перекопирует функционал из родительских классов в миксин:

function applyMixins(derivedCtor: any, baseCtors: any[]) {
    baseCtors.forEach(baseCtor => {
        Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
            derivedCtor.prototype[name] = baseCtor.prototype[name];
        });
    });
}

Затем применяем эту функцию:

applyMixins(Horse, [Animal, Movable]);

Первым параметром идет класс-миксин, а второй параметр - массив применяемых классов.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850