"Olá, Amigo! Ora aqui está um tópico que acho que você vai usar muito. Estou falando de herança. "

Para os não iniciados, a programação é como mágica. Então deixe-me começar com uma analogia…

Suponha que você seja um mágico que deseja criar um cavalo voador. Você poderia tentar conjurar um Pégaso. Mas como os cavalos voadores não ocorrem naturalmente, você terá muita dificuldade. Você teria muito trabalho a fazer. Seria muito mais fácil começar com um cavalo e convocar algumas asas.

Herança.  Vantagens da herança - 1

Na programação, chamamos esse processo de «herança» . Suponha que você precise escrever uma classe muito complexa. Você pode gastar muito tempo escrevendo código do zero e, em seguida, realizar testes demorados para encontrar bugs. Mas por que fazer isso da maneira mais difícil? É melhor dar uma olhada e ver se a classe que você está procurando já existe?

Digamos que você encontre uma classe que implemente 80% da funcionalidade de que você precisa. Você pode simplesmente copiar seu código em sua classe. Mas isso teria várias desvantagens:

1) A classe que você encontra pode já estar compilada em bytecode. Você pode não ter acesso ao seu código-fonte.

2) Você pode ter o código-fonte da aula, mas também trabalhar em uma empresa que pode ser processada por alguns bilhões se usar até 6 linhas do código de outra pessoa. E então eles vão te processar.

3) Isso leva à duplicação desnecessária de muitos códigos. E se o autor da outra classe encontrar um bug e corrigi-lo, você ainda terá o bug.

Existe uma solução mais elegante que não requer permissão legal para o código da classe original. Em Java, você pode simplesmente declarar a outra classe como pai de sua classe. Isso equivale a adicionar o código dessa classe à sua própria classe. Todos os dados e métodos da classe pai aparecerão em sua classe. Por exemplo, você pode herdar de um «cavalo», adicionar «asas» e obter um «Pégaso».

Herança.  Vantagens da herança - 2

"Muito interessante. Por favor, continue."

"A herança também tem outros usos. Suponha que você tenha dez classes muito semelhantes. Elas têm dados e métodos correspondentes. Você pode criar uma classe base especial, mover os dados (e métodos associados) para a classe base e ter essas dez classes herdar dela. Em outras palavras, para cada classe, você indica que ela tem uma classe pai, também conhecida como classe base."

"Assim como as vantagens da abstração só são verdadeiramente reveladas em conexão com o encapsulamento, as vantagens da herança são ampliadas pelo polimorfismo. Mas falarei sobre isso amanhã. Hoje vamos ver alguns exemplos de herança."

"Suponha que estamos escrevendo um programa de xadrez. Vamos precisar de aulas para as peças de xadrez. Quais aulas você sugeriria, amigo?"

"Rei, Rainha, Bispo, Cavalo, Torre e Peão."

"Muito bem. Você não perdeu nada."

"E quais dados você sugeriria armazenar nessas classes?"

"A posição de cada peça no tabuleiro (x e y) e o valor. Afinal, algumas peças são mais valiosas do que outras."

"E quais são as diferenças entre essas classes?"

"Eles diferem em como movem as peças. Em seu comportamento."

"Sim. Você pode defini-los como classes assim:"

class King
{
int x;
int y;
int worth;
void kingMove()
{
//code that defines,
//how the king moves
}
}
class Queen
{
int x;
int y;
int worth;
void queenMove()
{
//code that defines,
//how the queen moves
}
}
class Rook
{
int x;
int y;
int worth;
void rookMove()
{
//code that defines,
//how the rook moves
}
}
class Knight
{
int x;
int y;
int worth;
void knightMove()
{
//code that defines,
//how the knight moves
}
}
class Bishop
{
int x;
int y;
int worth;
void bishopMove()
{
//code that defines,
//how the bishop moves
}
}
class Pawn
{
int x;
int y;
int worth;
void pawnMove()
{
//code that defines,
//how the pawn moves
}
}

"Sim, é exatamente assim que eu escreveria."

"Mas veja como você poderia usar a herança para escrever menos código. Podemos mover métodos e dados idênticos para uma classe comum. Vamos chamá-la de ChessItem. Não faz sentido criar objetos ChessItem, pois eles não correspondem a nenhum peça de xadrez. Mas a aula seria extremamente útil:"

class King extends ChessItem
{
void kingMove()
{
//code that defines,
//how the king moves
}
}
class Queen extends ChessItem
{
void queenMove()
{
//code that defines,
//how the queen moves
}
}
class Rook extends ChessItem
{
void rookMove()
{
//code that defines,
//how the rook moves
}
}
 class ChessItem
{
int x;
int y;
int worth;
}
 
class Knight extends ChessItem
{
void knightMove()
{
//code that defines,
//how the knight moves
}
}
class Bishop extends ChessItem
{
void bishopMove()
{
//code that defines,
//how the bishop moves
}
}
class Pawn extends ChessItem
{
void pawnMove()
{
//code that defines,
//how the pawn moves
}
}

"Que interessante!"

"Com certeza! O benefício é especialmente grande em projetos contendo milhares de objetos diferentes e centenas de classes. Nesse caso, classes escolhidas corretamente podem não apenas simplificar significativamente a lógica, mas também reduzir o código necessário em um fator de dez."

"Então, o que você precisa fazer para herdar uma classe?"

"Depois de declarar uma classe, usamos a palavra-chave ' extends ', seguida do nome da classe pai. Você só pode herdar de uma classe. "

Herança.  Vantagens da herança - 3

A imagem mostra uma "vaca" herdada de um «porco». O «Porco» herda da «galinha», e a «galinha» herda do «ovo». Cada classe tem apenas um pai! Essa herança nem sempre é lógica. Se você só tem um porco, mas realmente precisa de uma vaca, os programadores muitas vezes não resistem ao desejo de fazer uma «vaca» do «porco».

"Mas e se eu quiser herdar de duas classes? Existe algo que eu possa fazer?!"

"Na verdade não. Classes Java não suportam herança múltipla de implementação: uma classe só pode ter uma única classe pai. Mas há herança múltipla de tipo, o que significa que uma classe pode implementar mais de uma interface. Isso atenua um pouco o problema. "

"Entendo. E o que é uma interface?"

"Falarei sobre interfaces amanhã. Por enquanto, vamos continuar nos aprofundando na herança."