Accediendo a miembro de la clase base


118

Vea el ejemplo de herencia del patio de recreo en el sitio de 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);

He cambiado una línea de código: la alerta en Horse.move(). Ahí quiero acceder super.name, pero eso vuelve justo undefined. IntelliSense sugiere que puedo usarlo y TypeScript se compila bien, pero no funciona.

¿Algunas ideas?

Respuestas:


179

Ejemplo de trabajo. Notas a continuación.

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. No es necesario que asigne manualmente el nombre a una variable pública. El uso public nameen la definición del constructor hace esto por usted.

  2. No necesita llamar super(name)desde las clases especializadas.

  3. Utilizando this.nameobras.

Notas sobre el uso de super.

Esto se trata con más detalle en la sección 4.9.2 de la especificación del lenguaje.

El comportamiento de las clases heredadas Animalno es diferente al comportamiento en otros lenguajes. Debe especificar la superpalabra clave para evitar confusiones entre una función especializada y la función de clase base. Por ejemplo, si llamó move()o this.move()estaría tratando con la función especializada Snakeo Horse, entonces el uso super.move()explícito llama a la función de clase base.

No hay confusión de propiedades, ya que son las propiedades de la instancia. No hay diferencia entre super.namey this.name- simplemente la hay this.name. De lo contrario, podría crear un Caballo que tuviera diferentes nombres dependiendo de si estaba en la clase especializada o en la clase base.


Excelente respuesta y gracias por la referencia a la especificación del idioma. ¿Conoce alguna documentación sobre por qué, por ejemplo, los accesos de propiedad de la clase base no están virtualizados y no se puede acceder a ellos a través de accesos primarios en la clase derivada (como lo están los métodos)?
— David Cuccia

La sección 4.8 cubre todo lo que se ha escrito hasta la fecha; tiende a ser un "este es el comportamiento", aunque en lugar de un "este es el motivo".
— Fenton

3
Gracias Steve Fenton. También me encontré con una discusión similar aquí: typescript.codeplex.com/discussions/418349 . Parece haber un desequilibrio en el idioma; Supongo que se tomó la decisión de mantener simple el JavaScript emitido, a diferencia de los métodos auxiliares "alternativos" para compensar la falta de soporte de JavaScript.
— David Cuccia

1

Está utilizando incorrectamente la palabra clave supery this. A continuación, se muestra un ejemplo de cómo funcionan:

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.

Explicación:

  1. Las primeras salidas de registro super.name, esto se refiere a la cadena prototipo del objeto tom, no al tomyo del objeto . Debido a que hemos agregado una propiedad de nombre en el Animal.prototype, se generará horseee.
  2. Las segundas salidas de registro this.name, la thispalabra clave se refiere al objeto tom en sí.
  3. El tercer registro se registra utilizando el movemétodo de la clase base Animal. Este método se llama desde el método de movimiento de la clase Horse con la sintaxis super.move(45);. El uso de la superpalabra clave en este contexto buscará un movemétodo en la cadena del prototipo que se encuentra en el prototipo Animal.

Recuerde que TS todavía usa prototipos bajo el capó y las palabras clave classy extendsson solo azúcar sintáctica sobre la herencia prototípica.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.