Zugriff auf ein Mitglied der Basisklasse


118

Siehe das Vererbungsbeispiel vom Spielplatz auf der TypeScript-Site:

class Animal {
  public name;
  constructor(name) {
    this.name = name;
  }
  move(meters) {
    alert(this.name + " moved " + meters + "m.");
  }
}

class Snake extends Animal {
  constructor(name) {
    super(name);
  }
  move() {
    alert("Slithering...");
    super.move(5);
  }
}

class Horse extends Animal {
  constructor(name) {
    super(name);
  }
  move() {
    alert(super.name + " is Galloping...");
    super.move(45);
  }
}

var sam = new Snake("Sammy the Python");
var tom: Animal = new Horse("Tommy the Palomino");

sam.move();
tom.move(34);

Ich habe eine Codezeile geändert: die Warnung in Horse.move(). Dort möchte ich zugreifen super.name, aber das kommt gerade zurück undefined. IntelliSense schlägt vor, dass ich es verwenden kann und TypeScript gut kompiliert, aber es funktioniert nicht.

Irgendwelche Ideen?

Antworten:


178

Arbeitsbeispiel. Anmerkungen unten.

class Animal {
    constructor(public name) {
    }

    move(meters) {
        alert(this.name + " moved " + meters + "m.");
    }
}

class Snake extends Animal {
    move() {
        alert(this.name + " is Slithering...");
        super.move(5);
    }
}

class Horse extends Animal {
    move() {
        alert(this.name + " is Galloping...");
        super.move(45);
    }
}

var sam = new Snake("Sammy the Python");
var tom: Animal = new Horse("Tommy the Palomino");

sam.move();
tom.move(34);
  1. Sie müssen den Namen nicht manuell einer öffentlichen Variablen zuweisen. Die Verwendung public namein der Konstruktordefinition erledigt dies für Sie.

  2. Sie müssen nicht super(name)aus den Fachklassen anrufen .

  3. Mit this.nameWerken.

Hinweise zur Verwendung von super.

Dies wird in Abschnitt 4.9.2 der Sprachspezifikation ausführlicher behandelt .

Das Verhalten der Klassen, von denen geerbt Animalwird, unterscheidet sich nicht vom Verhalten in anderen Sprachen. Sie müssen das superSchlüsselwort angeben , um Verwechslungen zwischen einer speziellen Funktion und der Basisklassenfunktion zu vermeiden. Wenn Sie beispielsweise aufgerufen haben move()oder this.move()sich mit dem Spezialisten Snakeoder der HorseFunktion befassen würden, super.move()ruft die Verwendung der Basisklassenfunktion explizit auf.

Es gibt keine Verwechslung von Eigenschaften, da es sich um die Eigenschaften der Instanz handelt. Es gibt keinen Unterschied zwischen super.nameund this.name- es gibt einfach this.name. Andernfalls könnten Sie ein Pferd erstellen, das unterschiedliche Namen hat, je nachdem, ob Sie in der Fachklasse oder in der Basisklasse waren.


Tolle Antwort und vielen Dank für den Hinweis auf die Sprachspezifikation. Ist Ihnen eine Dokumentation bekannt, warum beispielsweise Basisklassen-Eigenschafts-Accessoren nicht virtualisiert sind und über überschreibende Accessoren in der abgeleiteten Klasse zugänglich sind (wie Methoden)?
— David Cuccia

Abschnitt 4.8 behandelt alles, was bisher niedergeschrieben wurde - es handelt sich eher um ein "Dies ist das Verhalten", aber nicht um ein "Dies ist der Grund".
— Fenton

3
Vielen Dank, Steve Fenton. Ich bin auch gerade auf eine ähnliche Diskussion hier gestoßen: typescript.codeplex.com/discussions/418349 . Scheint ein Ungleichgewicht in der Sprache zu sein; Ich vermute, die Entscheidung wurde getroffen, das ausgegebene JavaScript einfach zu halten, im Gegensatz zu "Workaround" -Hilfemethoden, um den Mangel an JavaScript-Unterstützung zu kompensieren.
— David Cuccia

1

Sie verwenden das Schlüsselwort superund falsch this. Hier ist ein Beispiel, wie sie funktionieren:

class Animal {
    public name: string;
    constructor(name: string) { 
        this.name = name;
    }
    move(meters: number) {
        console.log(this.name + " moved " + meters + "m.");
    }
}

class Horse extends Animal {
    move() {
        console.log(super.name + " is Galloping...");
        console.log(this.name + " is Galloping...");
        super.move(45);
    }
}

var tom: Animal = new Horse("Tommy the Palomino");

Animal.prototype.name = 'horseee'; 

tom.move(34);
// Outputs:

// horseee is Galloping...
// Tommy the Palomino is Galloping...
// Tommy the Palomino moved 45m.

Erläuterung:

  1. Die ersten Protokollausgaben super.namebeziehen sich auf die Prototypkette des Objekts tom, nicht auf das Objekt tomselbst. Da wir der Eigenschaft name eine hinzugefügt haben Animal.prototype, wird Horseee ausgegeben.
  2. Bei der zweiten Protokollausgabe bezieht sich this.namedas thisSchlüsselwort auf das Tom-Objekt selbst.
  3. Das dritte Protokoll wird mit der moveMethode der Basisklasse Animal protokolliert . Diese Methode wird von der Horse Class Move-Methode mit der Syntax aufgerufen super.move(45);. Wenn Sie superin diesem Zusammenhang das Schlüsselwort verwenden, suchen Sie nach einer moveMethode in der Prototypenkette, die sich im Animal-Prototyp befindet.

Denken Sie daran, dass TS immer noch Prototypen unter der Haube verwendet und die Schlüsselwörter classund extendsnur syntaktischer Zucker über die prototypische Vererbung sind.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.