Přepsání metod

Boss zdědil od třídy Prisera metodu popis, takže se popíše jako každá příšera: Drak (300 životů). Boss by ale měl říct i to, v jaké je fázi. Odvozená třída může napsat vlastní verzi metody svého rodiče. Tomu se říká přepsání metody (anglicky override):

class Prisera {
    jmeno: string;
    zivoty: number;

    constructor(jmeno: string, zivoty: number) {
        this.jmeno = jmeno;
        this.zivoty = zivoty;
    }

    popis(): string {
        return `${this.jmeno} (${this.zivoty} životů)`;
    }
}

class Boss extends Prisera {
    faze: number = 1;

    override popis(): string {
        return `${super.popis()}, fáze ${this.faze}`;
    }
}

const prisery: Prisera[] = [new Prisera("Skřet", 30), new Boss("Drak", 300)];
for (const prisera of prisery) {
    console.log(prisera.popis());
}

Vypíše:

Skřet (30 životů)
Drak (300 životů), fáze 1

Nové jsou tu tři věci:

  • Metoda ve třídě Boss se jmenuje stejně jako ta ve třídě Prisera, a tak ji u bosse nahradí. Která verze se spustí, záleží na objektu, ne na typu proměnné: v cyklu je prisera pro TypeScript typu Prisera, ale druhý objekt je boss, a proto se spustí jeho vlastní popis.
  • super.popis() zavolá verzi rodiče. Boss nemusí opakovat, jak se příšery popisují: vezme jejich text a přidá k němu fázi. (Pozor: this.popis() by zavolalo metodu bosse samotnou, ta by zase volala sama sebe, a tak pořád dokola, dokud program neskončí chybou RangeError: Maximum call stack size exceeded.)
  • Klíčové slovo override říká: „Tahle metoda nahrazuje metodu rodiče.“ Je nepovinné, ale díky němu vás TypeScript může zkontrolovat.

Proč override pomáhá. Bez něj překlep v názvu nic nenahradí, jen přidá novou metodu:

class Prisera {
    jmeno: string;
    zivoty: number;

    constructor(jmeno: string, zivoty: number) {
        this.jmeno = jmeno;
        this.zivoty = zivoty;
    }

    popis(): string {
        return `${this.jmeno} (${this.zivoty} životů)`;
    }
}

class Boss extends Prisera {
    faze: number = 1;

    popsi(): string {
        return `${this.jmeno} (${this.zivoty} životů), fáze ${this.faze}`;
    }
}

const prisery: Prisera[] = [new Prisera("Skřet", 30), new Boss("Drak", 300)];
for (const prisera of prisery) {
    console.log(prisera.popis());
}

Vypíše:

Skřet (30 životů)
Drak (300 životů)

Metoda bosse se nikdy nezavolá a nic vám neřekne proč. Napište override popsi(): string a TypeScript chybu najde:

main.ts(18,14): error TS4117: This member cannot have an 'override' modifier because it is not declared in the base class 'Prisera'. Did you mean 'popis'?

Přepsaná metoda musí také odpovídat metodě rodiče: musí jít zavolat se stejnými argumenty a vrátit hodnotu typu, který vrací metoda rodiče. Kdyby popis bosse vracel číslo, TypeScript by ohlásil Property 'popis' in type 'Boss' is not assignable to the same property in base type 'Prisera'. (TS2416). Proto může boss zastoupit příšeru kdekoli: všechno, co jde udělat s příšerou, jde udělat i s bossem.

Pokyny

Drak by se měl popsat i se silou svého ohně, ale program vypíše jen Rudý drak (280 životů). Před drakovu metodu napište override. TypeScript pak chybu najde. Opravte ji, aby program vypsal:

Skřet (10 životů)
Rudý drak (280 životů), oheň 40

Drakova metoda opakuje, jak se popisují příšery. Pro tuto část místo toho použijte super.popis(). Program vypíše totéž.

Draci mají silné šupiny, a tak ztrácejí jen polovinu toho, co ostatní příšery. Přepište ve třídě Drak metodu ztratZivoty (s override) tak, aby zavolala verzi rodiče s polovičním počtem. Program vypíše:

Skřet (10 životů)
Rudý drak (290 životů), oheň 40

Začněte programovat zdarma

Registrací souhlasíte s provozními podmínkami a zásadami ochrany osobních údajů.

Nebo se registrujte pomocí:

8/9