Teoria
E aí, aqui é o Juan do Responde Aí, e agora vamos falar de mais um pilar da orientação a objetos, o Polimorfismo.
O que é polimorfismo?
Polimorfismo é um desses conceitos que são mais difíceis de explicar do que de fazer.
Polimorfismo significa “muitas formas”, e é exatamente isso que ele significa em C++. O polimorfismo é a capacidade de um objeto ou método assumir formas diferentes.
Mas o que isso quer dizer? Quando fazemos uma classe filha ela herda os métodos de uma classe mãe. Mas as vezes, um método herdado não é adequado, ou deveria agir de outra forma para uma certa classe filha específica.
A solução é usar os polimorfismos para escrever um novo método, porém usando o mesmo nome do método herdado. O usuário ainda pode usar o mesmo método, porém, sem saber que por baixo dos panos, o comportamento do método é diferente!
Ou seja, de maneira prática, o polimorfismo em C++ é a capacidade de reescrever um método que foi herdado.
Mas qual a vantagem do polimorfismo? A vantagem é que podemos escrever uma classe mãe com um método genérico bem simples que funcione com a maioria das classes filhas. E pras classes filhas que tiverem algo de especial, podemos usar polimorfismos para adaptar o conteúdo da classe mãe.
O polimorfismo é parecido com a sobrecarga que já estudamos. Mas existe uma diferença essencial: enquanto a sobrecarga representa variações de um método, o polimorfismo é a substituição de um método herdado, por um novo método com mesmo nome.
Métodos virtuais
Antes de a gente falar dos polimorfismos, a gente precisa conhecer mais uma palavra-chave do C++ o . Essa palavra-chave deve ser escrita nos membros da classe mãe que vão sofrer polimorfismo:
Usar a palavra não é obrigatório. Porém, é aconselhável utiliza-lo em todos os métodos em que você pretende aplicar polimorfismo
O deixa o código mais fácil de ler e entender, e facilita o uso dos ponteiros com classes que usam polimorfismo, e em situações em que um método faz chamada para um outro método que sofre polimorfismo. Usar a palavra-chave deixa claro pro programador e pro compilador que esse método sofrerá polimorfismo e será reescrito em classes filhas.
Usando polimorfismo
Para executar um polimorfismo é só escrever dentro da classe filha um método com o nome igual ao do método que está sendo substituído. Vamos fazer um exemplo bem simples.
O primeiro passo é criar uma classe mãe que tem um método virtual. No exemplo, criamos a que tem o método virtual , esse vai ser o método que sofrerá polimorfismo.
Dentro da vamos executar um polimorfismo. Para isso, é só a gente escrever um novo método com o mesmo nome e pronto! O polimorfismo está feito.
É como eu falei, fazer polimorfismo é mais fácil do que explicar polimorfismo. E pra usar as classes é só criar objetos e utilizar os métodos normalmente:
Viu só. A classe mãe e a classe filha possuem um método com o mesmo nome mas que efetuam atividades diferente!
Classes abstratas
Uma coisa interessante dos métodos virtuais é que eles podem ser completamente vazios. São os métodos virtuais puros, que são declarados colocando um “” na declaração do método:
Classes que possuem pelo menos um método virtual puro são chamadas de classes abstratas. E se todos os métodos da classe forem virtuais puros, então temos um interface.
Duas coisas vão acontecer quando você criar uma classe abstrata:
- Você não pode instanciar um objeto de uma classe abstrata. Isso gera um erro!
- Uma classe herdeira de uma classe abstrata deve ter todos os métodos virtuais sobrescritos através de polimorfismo.
Ou seja, você não consegue usar uma classe abstrata diretamente, porque o propósito das classes abstratas é servir de protótipos para criar classes filhas concretas. As classes abstratas servem de régua pra criar classes derivadas que sigam um determinado padrão.
Por outro lado, uma classe concreta é uma classe que é útil diretamente. Todas as classes que nós já fizemos até aqui eram classes concretas.
Exemplo de polimorfismo
Vamos ver agora um exemplo mais complexo de um programa de cadastro de funcionários.
A gente criou uma classe mãe , que tem os atributos , e e o método, e criamos três classes filhas , e :
O método simplesmente utiliza o atributo , o que funciona sem problemas nas classes e .
Porém, a remuneração do vendedor é composta de duas coisas: o salário mensal fixo mais uma comissão sobre o valor vendido. A solução é usar polimorfismo na classe filha .
Primeiro vamos fazer um código simples para a classe mãe . Repara no detalhe: a função vai sofrer polimorfismo. Então, deve ser uma função virtual. A primeira etapa é utilizar o nos métodos que sofrerão polimorfismos.
Em seguida, vamos desenvolver a classe que herda os membros de . Para efetuar uma herança a gente usa o operador e escreve
Em seguida, dentro da classe vamos adicionar o atributo :
E adicionar o método que recebe um parâmetro que corresponde ao valor vendido, atualiza o atributo e exibe uma mensagem pro usuário.
Ok! Até aqui tudo que fizemos foi herdar uma classe e adicionar novos membros na classe filha. Agora, vamos executar o polimorfismo! Executar o polimorfismo é só a gente reescrever o método virtual dentro da classe filha.
O novo método vai primeiro calcular uma comissão de para o vendedor. E depois vai imprimir o salário e o também a comissão!
E pronto! É só isso! A gente executou o polimorfismo!
Se aprofundando nos detalhes do Polimorfismo.
- O uso de métodos virtuais é recomendado, mas não é obrigatório!
- Métodos virtuais geram herdeiros virtuais.
- Criar um destrutor virtual é uma boa prática quando fazemos alocação dinâmica.
É perfeitamente possível aplicar polimorfismo em um método comum, ou seja, em um método que não tem a palavra . Porém, usar métodos virtuais facilita o trabalho com os ponteiros e em casos que um método da classe mãe executa um método com polimorfismo.
Um outro ponto é que quando um método virtual é herdado, todos os polimorfismos deste método serão considerados virtuais (mesmo sem usar a palavra chave ).
Isso quer dizer que um método virtual permanecerá virtual em todas as classes herdeiras e descendentes.
E é isso pessoal! Agora é só fazer uns exercícios de fixação.