Class - rozszerzanie typów

W poprzednich rozdziałach poznaliśmy konstruktory i klasy. Tworzone za ich pomocą obiekty dziedziczyły funkcjonalności ze swoich prototypów, a ich prototypy dziedziczyły ze swoich. Taka drabinka dziedziczenia tworzona była dla nas w zasadzie automatycznie.

My jako programiści możemy też sprawić, by dany typ dziedziczył z innego typu odpowiednio go rozszerzając.

Rozszerzanie typów

Aby rozszerzyć dany typ obiektów, skorzystamy z instrukcji extends:

class Enemy { //to może być też konstruktor
    constructor(x, y) {
        this.x = x;
        this.y = y;
        this.type = "normalny";
    }

    fly() {
        return this.type + " - lecę";
    }
}

class EnemyShooter extends Enemy {
    constructor(x, y) {
        super(x, y);
        this.type = "strzelający";
    }

    shoot() {
        return this.type + " - strzelam";
    }
}

const enemyNormal = new Enemy(10, 20);
console.log(enemyNormal.fly()); //"normalny - lecę"
console.log(enemyNormal.shoot()); //błąd - nie ma takiej metody

const enemyShooter = new EnemyShooter(20, 30);
console.log(enemyShooter.fly()); //"strzelający - lecę"
console.log(enemyShooter.shoot()); //"strzelający - strzelam"

W konstruktorze klasy rozszerzającej pojawiła nam się instrukcja super(), która w przypadku konstruktora służy do wywołania kodu z konstruktora klasy którą rozszerzamy. Jeżeli wymagał on jakiś wartości, powinniśmy je przekazać w nawiasach super().

W przypadku rozszerzania innych metod, także skorzystamy z instrukcji super(), po której podajemy nazwę metody, którą chcemy rozszerzyć:

I tutaj ponownie - gdyby oryginalna funkcja fly() wymagała parametrów, przydało by się je podać, inaczej rozszerzana funkcja odpalona była by z wartościami undefined.

Jeżeli chcemy daną metodę przesłonić (czyli by nic nie dziedziczyła z klasy rozszerzanej) zwyczajnie nie korzystamy z instrukcji super():

A jeżeli chcemy by dana metoda (w tym konstruktor), została w niezmienionej postaci względem klasy, którą właśnie rozszerzamy, po prostu pomijamy jej kod:


Podobne do powyższych operacji możemy też wykonać za pomocą konstruktorów. Niestety w przypadku tamtej składni kod jest bardziej skomplikowany, a i mamy mniejsze możliwości działania, ponieważ nie możemy swobodnie rozszerzać wbudowanych typów. W dzisiejszych czasach do rozszerzania typów polecam pozostać przy klasach. Jeżeli chcesz zobaczyć, jak to wyglądało.

Rozszerzanie wbudowanych typów

Tworzenie własnych typów danych na bazie wbudowanych w starszych wersjach Javascript nie było trywialną sprawą, co pokazują liczne wątki. Na szczęście zmieniło się to wraz z wprowadzeniem klas:

Last updated