4.4 Herança
4.4.1 Herança Simples
O conceito de herança é construído sobre a ideia de que algumas classes estão intimamente ligadas a outras classes, e que por conta disso, compartilham características em comum (i.e., atributos, métodos, comportamentos, etc.).
Partindo dessa ideia, podemos estabelecer um relacionamento hierárquico entre classes, em que a classe no topo da árvore é a classe mais genérica (geralmente chamada de classe base, ou classe mãe) e à medida que descemos de nível na hierarquia, temos uma nova classe (classe derivada, ou classe filha), que é uma especialização da classe acima. Por conta disso, geralmente nos referimos à relação que vincula uma classe derivada a sua classe base pela frase "Y é um tipo de X" ou "Y é uma especialização da classe X", sendo X a classe base e Y a classe derivada .
Figura 2 – Árvore hierárquica representando o conceito de herança aplicado a classe veículo.
Fonte: Elaborada pelo autor.
O mecanismo de herança permite que uma classe seja definida a partir de uma outra classe já existente, com isso a definição da classe derivada herda automaticamente atributos, métodos e comportamentos da classe base. Por conta disso, herança é considerada uma técnica poderosa, uma vez que encoraja a reusabilidade durante o desenvolvimento e provê uma grande economia de tempo, sem perda de qualidade no desenvolvimento (pois você não precisa reescrever, testar, depurar e manter o código herdado) .
Para exemplificar, imaginemos que precisamos definir uma classe Estudante, a qual possui atributos como número de matrícula, curso, período, etc, ou seja, coisas que remetem à vida escolar de um estudante. Contudo, é relevante também para quem manipulará os objetos do tipo Estudante, saber qual o nome do estudante, sua data de nascimento, seu RG, etc., ou seja, coisas que remetem à pessoa propriamente dita.
Podemos então utilizar o mecanismo de herança e definir a classe Estudante herdando a classe Pessoa que já definimos em exemplos anteriores, uma vez que um estudante é uma especialização de pessoa, ou seja, um tipo especifico de pessoa e que, portanto, além de possuir suas características especificas (matricula, curso, etc.) também deve possuir características de uma pessoa (nome, data de nascimento, etc.).
Utilizando o mecanismo de herança, a definição da classe Estudante fica bem mais simples do que escrever a classe desde o início, como ilustrado no Exemplo 20:
Exemplo 20:
public class Estudante : Pessoa
{
public int matricula;
public string instituicao;
public string curso;
public string periodo;
public int turma;
public DateTime ingresso;
public DateTime jubilamento;
public void apresentarSe()
{
Console.Write("Olá, meu nome é " + nome);
Console.Write(", tenho " + idade + "anos ");
Console.Write("e atualmente estudo " + curso);
Console.Write(" na " + instituicao);
}
}
Note que entre Estudante e Pessoa há um sinal de dois pontos, o que na definição de uma classe em C# indica que a classe Estudante herda a classe Pessoa.
Feito isto os objetos do tipo Estudante compartilham as características de uma Pessoa, como ilustrado no Exemplo 21:
Exemplo 21:
Estudante fulano = new Estudante();
fulano.nome = "Fulano de Tal";
fulano.matricula = 13101659;
fulano.instituicao = "FATEC-SP";
fulano.curso = "Análise e Desenvolvimento de Sistemas";
fulano.setIdade(20);
fulano.falar();
fulano.apresentarSe();
4.4.2 Herança múltipla
Algumas linguagens orientadas a objetos como C++, Scala e Python também oferecem o mecanismo de herança múltipla, que permite que uma classe herde de mais de uma classe ao mesmo tempo.
Figura 3 – Representação do conceito de herança múltipla aplicado a classe CarroAnfibio.
Fonte: Elaborada pelo autor.
Contudo herança múltipla tem sido uma questão sensível por muitos anos, pois pode aumentar a complexidade na programação e gerar ambiguidade em situações onde mais de uma classe base possui atributos ou métodos como mesmo nome, embora hoje já haja abordagens que resolvem essa ambigüidade (i.e., em C++ por exemplo, é usado classePai::AtributoAmbiguo para explicitar de qual classe o atributo ambíguo será acessado). Ilustração no Exemplo 22 da implementação de herança múltipla em C++.
Exemplo 22:
class Estudante
{
public:
void apresentarSe() { ... }
protected:
int idade;
string nome;
};
class Trabalhador
{
public:
void trabalhar() { ... }
protected:
double salario;
string nome;
};
class Estagiario : public Estudante, public Trabalhador
{
...
};