Acessando membro da classe base


118

Veja o exemplo de herança do playground no 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);

Mudei uma linha de código: o alerta em Horse.move(). Aí quero acessar super.name, mas só retorna undefined. O IntelliSense está sugerindo que eu posso usá-lo e o TypeScript compila bem, mas não funciona.

Alguma ideia?

Respostas:


179

Exemplo de trabalho. Notas abaixo.

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. Você não precisa atribuir manualmente o nome a uma variável pública. Usar public namena definição do construtor faz isso por você.

  2. Você não precisa ligar super(name)das aulas especializadas.

  3. Usando this.nameobras.

Notas sobre o uso de super.

Isso é abordado com mais detalhes na seção 4.9.2 da especificação da linguagem.

O comportamento das classes que herdam de Animalnão é diferente do comportamento em outras linguagens. Você precisa especificar a superpalavra - chave para evitar confusão entre uma função especializada e a função da classe base. Por exemplo, se você chamou move()ou this.move()estaria lidando com a função especializada Snakeou Horse, usar super.move()chama explicitamente a função da classe base.

Não há confusão de propriedades, pois são as propriedades da instância. Não há diferença entre super.namee this.name- simplesmente há this.name. Caso contrário, você poderia criar um Cavalo com nomes diferentes, dependendo se você estava na classe especializada ou na classe base.


Ótima resposta, e obrigado pela referência à especificação do idioma. Você está ciente de qualquer documentação sobre por que, por exemplo, os acessadores de propriedade da classe base não são virtualizados e acessíveis por meio de acessadores de substituição na classe derivada (como os métodos são)?
— David Cuccia

A Seção 4.8 cobre tudo que foi escrito até agora - tende a ser um "este é o comportamento", embora ao invés de um "este é o porquê".
— Fenton

3
Obrigado Steve Fenton. Também me deparei com uma discussão semelhante aqui: typescript.codeplex.com/discussions/418349 . Parece haver um desequilíbrio na linguagem; meu palpite é que a decisão foi tomada para manter o JavaScript emitido simples, em oposição aos métodos auxiliares de "solução alternativa" para compensar a falta de suporte ao JavaScript.
— David Cuccia

1

Você está usando incorretamente a palavra super- thischave e . Aqui está um exemplo de como eles funcionam:

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.

Explicação:

  1. As primeiras saídas de log super.namereferem-se à cadeia de protótipo do objeto tom, não ao tompróprio objeto . Como adicionamos uma propriedade de nome no Animal.prototype, horseee será gerado.
  2. As saídas do segundo log this.name, a thispalavra - chave se refere ao próprio objeto tom.
  3. O terceiro log é registrado usando o movemétodo da classe base Animal. Este método é chamado do método de movimento da classe Horse com a sintaxe super.move(45);. Usar a superpalavra - chave neste contexto procurará um movemétodo na cadeia de protótipo que se encontra no protótipo Animal.

Lembre-se de que o TS ainda usa protótipos sob o capô e as palavras class- extendschave e são apenas açúcar sintático em relação à herança prototípica.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.