He

Herança em JavaScript

1 exercício

Sobre Herança

A herança é uma forma de criar relações pai-filho entre classes. A classe filha (por vezes chamada de subclasse) tem acesso ao comportamento e aos dados definidos pela classe pai (por vezes chamada de superclasse).

class Pet {
  constructor(name) {
    this.name = name;
  }

  introduce() {
    console.log(`This is my pet, ${this.name}.`);
  }
}

class Dog extends Pet {}

const dog = new Dog('Otis');
dog.introduce();
// => This is my pet, Otis.

A palavra-chave extends na declaração da classe filha estabelece uma relação com a classe pai através da cadeia de protótipos.

Os objetos criados pelo construtor da classe filha têm o protótipo da classe pai na sua cadeia de protótipos, o que dá acesso a todos os métodos ou dados definidos pela classe pai.

const dog = new Dog('Otis');

Dog.prototype.isPrototypeOf(dog); // => true
Pet.prototype.isPrototypeOf(dog); // => true
Pet.prototype.isPrototypeOf(Dog.prototype); // => true

Pet.prototype.hasOwnProperty('introduce'); // => true
Dog.prototype.hasOwnProperty('introduce'); // => false
dog.hasOwnProperty('introduce'); // => false

Construtores

Se a classe filha não definir uma função construtora, é usada a função construtora da classe pai. No entanto, se a classe filha definir uma função construtora própria, é preciso chamar explicitamente o construtor da classe pai. Para invocar o construtor da classe pai a partir do âmbito do construtor da classe filha, usa-se a palavra-chave super.

class Pet {
  constructor(name) {
    this.name = name;
  }
}

class Dog extends Pet {
  constructor(name, breed) {
    super(name);
    this.breed = breed;
  }
}

const dog = new Dog('Otis', 'Pug');

Como o construtor da classe pai é responsável por inicializar um novo objeto e atribuí-lo a this, tem de ser chamado antes de o construtor da classe filha usar this.

class Dog extends Pet {
  constructor(name, breed) {
    // using 'this' before calling the parent constructor with 'super'
    this.breed = breed;
    super(name);
  }
}

const dog = new Dog('Otis', 'Pug');
// => ReferenceError: Must call super constructor in derived class before accessing 'this'...

Definir métodos na classe filha

Uma classe filha pode definir comportamento próprio, para além do comportamento herdado da classe pai.

Esta é uma das principais razões para usar herança: ter classes filhas especializadas, com dados e métodos próprios, relacionadas através de métodos e dados partilhados fornecidos pela classe pai.

class Dog extends Pet {
  constructor(name, breed) {
    super(name);
    this.breed = breed;
  }

  describe() {
    console.log(`${this.name} is a ${this.breed}.`);
  }
}

const dog = new Dog('Otis', 'Pug');
dog.introduce();
dog.describe();
// => 'This is my pet, Otis.'
// => 'Otis is a Pug.'

Substituir métodos herdados da classe pai

Uma classe filha também pode substituir o comportamento de um método definido pela classe pai e trocá-lo ou ampliá-lo com o comportamento definido pela classe filha.

class Cat extends Pet {
  // replacing parent class behavior
  introduce() {
    console.log(`This is my cat, ${this.name}.`);
  }
}

class Dog extends Pet {
  constructor(name, breed) {
    super(name);
    this.breed = breed;
  }

  describe() {
    console.log(`${this.name} is a ${this.breed}.`);
  }

  // extending parent class behavior
  introduce() {
    super.introduce();
    this.describe();
  }
}

const cat = new Cat('Milo');
cat.introduce();
// => 'This is my cat, Milo.'

const dog = new Dog('Otis', 'Pug');
dog.introduce();
// => This is my pet, Otis.
// => Otis is a Pug.

Para chamar um método definido na classe pai a partir do corpo de um método com o mesmo nome na classe filha, é preciso usar a palavra-chave super para referenciar a classe pai.

Editar via GitHub A ligação abre numa nova janela ou separador

Aprende Herança