Vererbung
Ein Endgegner ist ein Monster mit etwas Extra: Er kämpft in Phasen. Du könntest die ganze Klasse Monster kopieren und ein Feld hinzufügen, aber dann müsste jede Änderung an Monstern doppelt gemacht werden. Stattdessen kann eine Klasse eine andere erweitern (englisch extend):
class Monster {
name: string;
leben: number;
constructor(name: string, leben: number) {
this.name = name;
this.leben = leben;
}
beschreibe(): string {
return `${this.name} (${this.leben} Leben)`;
}
}
class Endgegner extends Monster {
phase: number;
constructor(name: string, leben: number, phase: number) {
super(name, leben);
this.phase = phase;
}
}
const drache = new Endgegner("Drache", 300, 1);
console.log(drache.beschreibe());
console.log(drache);Das gibt aus:
Drache (300 Leben)
Endgegner { name: "Drache", leben: 300, phase: 1 }class Endgegner extends Monster bedeutet: Ein Endgegner hat alles, was ein Monster hat, die Felder name und leben und die Methode beschreibe, plus das, was Endgegner hinzufügt, hier das Feld phase. Das nennt man Vererbung: Endgegner erbt von Monster. Monster ist die Elternklasse, und Endgegner ist eine abgeleitete Klasse (oder Unterklasse). Es ist wie interface Endgegner extends Monster aus der Lektion Objekttypen, nur dass eine Klasse nicht nur die Form erbt, sondern auch den Code: drache.beschreibe() funktioniert, obwohl Endgegner selbst keine Methode beschreibe schreibt.
Der Konstruktor der Elternklasse: super. Die Felder der Elternklasse werden vom Konstruktor der Elternklasse gesetzt, also muss der Konstruktor einer abgeleiteten Klasse ihn zuerst aufrufen. super(name, leben) führt den Konstruktor von Monster mit diesen Argumenten aus. Erst dann ist das Objekt bereit, und der Konstruktor kann mit seinen eigenen Feldern weitermachen. Ohne super meldet TypeScript:
class Monster {
name: string;
leben: number;
constructor(name: string, leben: number) {
this.name = name;
this.leben = leben;
}
}
class Endgegner extends Monster {
phase: number = 1;
constructor(name: string, leben: number) {
console.log("Ein Endgegner erscheint!");
}
}TypeScript meldet:
main.ts(14,5): error TS2377: Constructors for derived classes must contain a 'super' call.Wenn du this vor super(…) verwendest, bekommst du 'super' must be called before accessing 'this' in the constructor of a derived class. (TS17009). Und super prüft seine Argumente wie jeder Aufruf: TS2554, wenn eines fehlt. Eine abgeleitete Klasse, die keinen eigenen Konstruktor braucht, kann ihn weglassen; dann verwendet sie den der Elternklasse: Mit nur phase: number = 1; in Endgegner würdest du new Endgegner("Drache", 300) schreiben.
Ein Endgegner ist ein Monster. Überall, wo ein Monster erwartet wird, passt ein Endgegner: in einem Monster[]-Array oder als Argument von function greifAn(monster: Monster). Über den Typ Monster kannst du allerdings nur verwenden, was jedes Monster hat. Bei const gegner: Monster[] = [goblin, drache]; ergibt gegner[1].phase die Meldung Property 'phase' does not exist on type 'Monster'. (TS2339).
So schreibst du es:
Anweisungen
- 1
Schreibe eine Klasse
Drache, dieMonstererweitert und ein Feldfeuerkraft(eine Zahl) hinzufügt. Ihr Konstruktor hat drei Parameter,name,lebenundfeuerkraft: Er gibt die ersten beiden ansuperweiter und setztfeuerkraftselbst. - 2
Erzeuge über dem Array
gegnermitconst drache = new Drache("Roter Drache", 300, 40);einen Drachen und fügedrachedem Array hinzu. Das Programm gibt aus:Goblin (30 Leben) Wolf (25 Leben) Roter Drache (300 Leben) - 3
Füge
Dracheeine MethodespeiFeuer(): stringhinzu. Sie gibt den Namen und die Feuerkraft des Drachen so zurück:Roter Drache speit Feuer: 40 Schaden. Gib am Ende des Programmsdrache.speiFeuer()aus. (Rufe sie aufdracheauf, nicht aufgegner[2]: Über den TypMonsterweiß TypeScript nicht, dass es ein Drache ist.) Das Programm gibt aus:Goblin (30 Leben) Wolf (25 Leben) Roter Drache (300 Leben) Roter Drache speit Feuer: 40 Schaden