Accès au membre de la classe de base


118

Voir l'exemple d'héritage du terrain de jeu sur le site TypeScript:

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);

J'ai changé une ligne de code: l'alerte en Horse.move(). Là, je veux accéder super.name, mais cela revient juste undefined. IntelliSense suggère que je peux l'utiliser et TypeScript compile bien, mais cela ne fonctionne pas.

Des idées?

Réponses:


179

Exemple de travail. Notes ci-dessous.

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. Vous n'avez pas besoin d'attribuer manuellement le nom à une variable publique. L'utilisation public namedans la définition du constructeur le fait pour vous.

  2. Vous n'avez pas besoin d'appeler super(name)des classes spécialisées.

  3. Utiliser des this.nameœuvres.

Remarques sur l'utilisation de super.

Ceci est traité plus en détail dans la section 4.9.2 de la spécification du langage.

Le comportement des classes héritant de Animaln'est pas différent de celui des autres langages. Vous devez spécifier le supermot - clé afin d'éviter toute confusion entre une fonction spécialisée et la fonction de classe de base. Par exemple, si vous avez appelé move()ou que this.move()vous avez affaire à la fonction spécialisée Snakeou Horse, l'utilisation de super.move()la fonction appelle explicitement la fonction de classe de base.

Il n'y a pas de confusion des propriétés, car ce sont les propriétés de l'instance. Il n'y a pas de différence entre super.nameet this.name- il y a simplement this.name. Sinon, vous pouvez créer un cheval qui porte des noms différents selon que vous êtes dans la classe spécialisée ou dans la classe de base.


Excellente réponse, et merci pour la référence à la spécification de la langue. Connaissez-vous une documentation expliquant pourquoi, par exemple, les accesseurs de propriété de classe de base ne sont pas virtualisés et accessibles via des accesseurs de substitution dans la classe dérivée (comme le sont les méthodes)?
— David Cuccia

La section 4.8 couvre tout ce qui a été écrit à ce jour - elle a tendance à être un "c'est le comportement", bien que plutôt qu'un "c'est pourquoi".
— Fenton

3
Merci Steve Fenton. Je viens également de tomber sur une discussion similaire ici: typescript.codeplex.com/discussions/418349 . Semble être un déséquilibre dans la langue; je suppose que la décision a été prise de garder le JavaScript émis simple, par opposition aux méthodes d'aide «de contournement» pour compenser le manque de support JavaScript.
— David Cuccia

1

Vous n'utilisez pas correctement le mot super- thisclé et . Voici un exemple de leur fonctionnement:

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.

Explication:

  1. Les premières sorties du journal super.name, cela fait référence à la chaîne prototype de l'objet tom, pas à l'objet tomself. Parce que nous avons ajouté une propriété de nom sur le Animal.prototype, horseee sera affiché.
  2. Le deuxième journal sort this.name, le thismot - clé fait référence à l'objet tom lui-même.
  3. Le troisième journal est enregistré à l'aide de la moveméthode de la classe de base Animal. Cette méthode est appelée à partir de la méthode de déplacement de la classe Horse avec la syntaxe super.move(45);. L'utilisation du supermot - clé dans ce contexte cherchera une moveméthode sur la chaîne prototype qui se trouve sur le prototype Animal.

N'oubliez pas que TS utilise toujours des prototypes sous le capot et que les mots-clés classet ne extendssont que du sucre syntaxique par rapport à l'héritage prototypique.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.