O que é Herança de Classe e Como Ela Funciona?
Em programação, herança permite que você defina classes que herdam propriedades e métodos de outras classes.
Por exemplo, um
Car é um tipo de Vehicle, então você poderia definir uma classe Vehicle com as propriedades e métodos mais gerais que são comuns a todos os tipos de veículos e depois definir uma classe Car que herda as propriedades e métodos da classe Vehicle.
Essa relação "is a" é característica da herança. Neste exemplo, Car é uma forma mais especializada de Vehicle.
Existem dois conceitos principais que você deve conhecer para começar a trabalhar com herança: parent class e child class.
Uma classe pai é uma classe que funciona como um modelo para outras classes. Ele define propriedades e métodos que são herdados por outras classes.
Uma classe filha é uma classe que herda as propriedades e métodos de outra classe. Classes filhas também podem estender a funcionalidade de suas classes pai adicionando novas propriedades e métodos.
No nosso exemplo anterior, Vehicle seria a classe pai da classe Car enquanto a classe Car seria a classe filha de Vehicle.
Uma classe pai pode ter múltiplas classes filhas.
Em JavaScript, usamos a palavra-chave extends para implementar herança. Esta palavra-chave indica que uma classe é a classe filha de outra classe.
Neste exemplo, no qual temos apenas as primeiras linhas das definições das classes, você pode ver que a classe Car estende a classe Vehicle, então Car herda de Vehicle.
class Vehicle {
// Implementation of Vehicle...
}
class Car extends Vehicle {
// Implementation of Car...
}
Vamos supor que a classe Vehicle tenha duas propriedades: brand e year. Você pode ver isso no código atualizado.
Car tem um método chamado honk. No entanto, note que a classe Car não possui seu próprio construtor. Vamos ver se ele herda as propriedades.
class Vehicle {
constructor(brand, year) {
this.brand = brand;
this.year = year;
}
}
class Car extends Vehicle {
honk() {
console.log("Honk! Honk!");
}
}
Para definir uma instância de Car, você precisará passar dois argumentos: brand e year. Neste caso, a marca é G.E.A.R ACADEMY Motors e o ano é 2019.
let myCar = new Car("G.E.A.R ACADEMY Motors", 2019);
Se você tentar acessar essas propriedades e chamar o método usando a notação de ponto:
console.log(myCar.brand);
console.log(myCar.year);
myCar.honk();
Aqui está o exemplo completo:
class Vehicle {
constructor(brand, year) {
this.brand = brand;
this.year = year;
}
}
class Car extends Vehicle {
honk() {
console.log("Honk! Honk!");
}
}
let myCar = new Car("G.E.A.R ACADEMY Motors", 2019);
console.log(myCar.brand);
console.log(myCar.year);
myCar.honk();
De fato, a saída está correta, então essas propriedades e método são definidos na instância Car e você acabou de se poupar de muita repetição de código ao herdar essas propriedades da classe Vehicle.
Neste exemplo, a classe filha não tinha nenhuma propriedade adicional. É por isso que a classe não tinha um construtor, apenas um método.
Se você realmente precisar adicionar propriedades adicionais, será necessário definir um construtor.
Vamos ver um exemplo.
class Vehicle {
constructor(brand, year) {
this.brand = brand;
this.year = year;
}
}
class Car extends Vehicle {
constructor(brand, year, numDoors) {
super(brand, year);
this.numDoors = numDoors;
}
}
Desta vez, adicionaremos uma propriedade numDoors à subclasse Car.
Você pode ver que agora esta classe tem um construtor no código atualizado. Dentro do construtor, há uma chamada para super(), passando os argumentos brand e year.
super() invoca o construtor da superclasse, então ao usar super(brand, year) você estará essencialmente definindo as propriedades da superclasse na subclasse. Este é outro termo que você pode usar - superclass é a classe pai e subclass é a classe filha.
Então, a linha this.numDoors = numDoors define uma nova propriedade que pertence exclusivamente à classe Car, o número de portas (numDoors).
Esta é uma forma de estender a classe Vehicle, adicionando uma propriedade que é exclusiva das instâncias Car.
Isso é um exemplo de extensibilidade, uma das vantagens fundamentais da herança.
Agora, se você criar uma instância da classe Car, verá que ela tem as três propriedades: brand, year e numDoors. Você também precisará passar os argumentos necessários quando criar a instância.
let myCar = new Car("G.E.A.R ACADEMY Motors", 2019, 4);
Se você imprimir os valores dessas propriedades com console.log():
console.log(myCar.brand);
console.log(myCar.year);
console.log(myCar.numDoors);
Aqui está o exemplo completo:
class Vehicle {
constructor(brand, year) {
this.brand = brand;
this.year = year;
}
}
class Car extends Vehicle {
constructor(brand, year, numDoors) {
super(brand, year);
this.numDoors = numDoors;
}
}
let myCar = new Car("G.E.A.R ACADEMY Motors", 2019, 4);
console.log(myCar.brand);
console.log(myCar.year);
console.log(myCar.numDoors);
As principais vantagens da herança são reutilização de código, modularidade, extensibilidade e melhoria na estrutura do código.
Ao implementar uma hierarquia, você pode reutilizar o código que já escreveu para uma classe pai na classe filha, evitando repetições.
A herança também promove modularidade ao dividir sistemas complexos em componentes mais simples na hierarquia.
Além disso, poder estender a funcionalidade da classe pai facilita a adaptação a requisitos em mudança e a adição de novos recursos mais tarde no processo de desenvolvimento.
Finalmente, a estrutura hierárquica pode tornar seu código mais fácil de entender e manter.
Esses são os fundamentos da herança. Ao entender como a herança funciona, você pode projetar programas orientados a objetos bem estruturados, fáceis de manter e extensíveis.Este módulo não possui perguntas. Marque como concluído.