Typescript - mixins, czyli sposób na wielokrotne dziedziczenie
Ostatnio rozpocząłem przygodę z językiem TypeScript. Wśród zalet odróżniających go od swojego przodka (języka JavaScript) jest silne typowanie i dużo bardziej intuicyjna obiektowość. Jednym z ograniczeń jest pojedyncze dziedziczenie (przypadłość wielu języków programowania). Na szczęście istnieje sposób na obejście tego problemu.
Załóżmy, że mamy klasy odpowiedzialne za podróż samochodem i statkiem:
class Car {
drive() {
console.log("I can drive");
}
}
class Ship {
sail() {
console.log("I can sail");
}
}
Chcąc dodać nową klasę, wzorowaną na amfibii, nie możemy zdefiniować standardowego dziedziczenia z tych dwóch klas z pomocą słówka extends
.
Zamiast tego, wystarczy wesprzeć się słówkiem implements
aby zadeklarować klasę będącą ich kombinacją oraz zadeklarować niezbędne metody:
class Amphibian implements Car, Ship {
drive: () => void;
sail: () => void;
}
Aby połaczyć deklaracje metod z implementacją, możemy wesprzeć się funkcją applyMixins
:
applyMixins(Amphibian, [Car, Ship]);
Którą można zadeklarować jako:
function applyMixins(derivedClass: any, baseClasses: any[]) {
baseClasses.forEach(baseClass => {
Object.getOwnPropertyNames(baseClass.prototype).forEach(name => {
derivedClass.prototype[name] = baseClass.prototype[name];
});
});
}
W efekcie powinniśmy uzyskać możliwość utworzenia nowej instancji obiektu odpowiedzialnego za sterowanie amfibią z możliwością poruszania się po lądzie i wodzie:
const amphibian = new Amphibian();
amphibian.drive();
amphibian.sail();