C# - Polimorfismo (revisão)
Neste artigo vamos rever os conceitos de herança, encapsulamento e polimorfismo. |
Existem alguns conceitos básicos que estão vinculados ao conceito da programação orientada a objetos. São eles :
A herança permite implementar a funcionalidade
a sua
classe de tomar emprestado o resto da estrutura e comportamento
de classes de nível mais alto.
Pensemos em uma classe carro.
Esta classe define os comportamentos e atributos de um carro; E existem atributos que serão comum a todos os carros.
As rodas e o motor são atributos comuns a qualquer carro. Já uma Ferrari possui atributos que somente ela possui : valor e potência por exemplo.
A definição formal para
herança seria:
- Herança é um mecanismo que
permite que características comuns a diversas classes sejam
agrupadas em uma classe base, ou
superclasse. A partir de uma classe base, outras classes podem
ser especificadas.
- Cada classe derivada ou
subclasse apresenta as características (estrutura e métodos) da
classe base e acrescenta a elas o que for definido de
particularidade para ela
Encapsular significa "ocultar informações" ele define que cada objeto contém todos os detalhes de implementação necessários sobre como ele funciona e oculta os detalhes internos sobre como ele executa os serviços.
Quando você acelera um carro você esta enviando uma mensagem ao motor do carro usando o acelerador e o carro sabe que tem que acelerar.
Você não precisa saber como é feita a aceleração no motor você apenas pisa fundo no acelerador, a implementação de como é feita a aceleração esta encapsulada do cliente.
Voltando à classe carro podemos aplicar o encapsulamento definindo propriedades na classe de forma que o acesso a seus atributos possa ser feito somente acessando as propriedades.
Polimorfismo significa muitas formas , na orientação a objetos você pode enviar uma mesma mensagem para diferentes objetos e fazê-los responder da maneira correta.
Você pode
enviar a mensagem mover para cada objeto
semelhante a um veiculo e cada um vai se comportar de maneira
diferente para atender a sua solicitação.
Quando uma mesma mensagem pode ser processada de diferentes formas temos um exemplo de polimorfismo.
Uma definição mais formal diria:
"Polimorfismo é o princípio pelo
qual duas ou mais classes derivadas de uma mesma superclasse
podem invocar métodos que têm a mesma identificação
(assinatura) mas comportamentos distintos, especializados para
cada classe derivada, usando para tanto uma referência a um
objeto do tipo da superclasse"
Usando polimorfismo podemos :
Existem dois tipos básicos de polimorfismo:
O polimorfismo em tempo de compilação utiliza a sobrecarga de métodos e operadores sendo também chamado de ligação precoce (early binding). A utilização da sobrecarga de métodos realiza a tarefa com distintos parâmetros de entrada.
O polimorfismo em tempo de execução pode ser feito usando herança e métodos virtuais. Quando sobrescrevemos(override) os métodos virtuais estamos alterando o comportamento dos métodos para a classe derivada. Isto também é conhecido como ligação tardia (late binding).
Vamos agora passar para prática essa teoria...
Prática 1 - Polimorfismo
com herança e métodos virtuais
Pegando 'carona' no exemplo da classe carro vamos aumentar a abstração do exemplo e aplicar os conceitos de polimorfismo.
Imagine uma classe Veiculo que define os comportamentos e atributos de qualquer veículo e não apenas de carros.
Uma característica básica de qualquer veículo é o movimento, logo, nossa classe Veiculo pode expressar isso através de um método Mover().
Outra característica básica de qualquer veículo seria poder parar, afinal nenhum veículo fica eternamente em movimento e isso seria expresso na classe veículo por um método Parar().
Então podemos criar uma classe Veiculo contendo esses métodos e usar o mecanismo da herança para que outras classes herdem os atributos e comportamentos comuns.
Vamos criar uma classe Veiculo, uma classe Automovel e uma classe Aeronave onde as duas últimas irão herdar da classe Veiculo e veremos como promover o polimorfismo usando o mecanismo da herança.
Vemos isso representado no diagrama abaixo:
Seguindo essa orientação poderíamos vamos criar um novo projeto usando o Visual C# 2010 Express Edition do tipo Console Application com o nome CSharp_Polimorfismo;
No menu Project selecione o Item Add Class para criar as classes Veiculo, Aeronave e Automovel.
A seguir defina o código de cada classe conforme abaixo:
1- Classe Veiculo
Nota: Em uma implementação mais robusta a classe Veiculo seria definida como abstrata e os métodos Mover e Parar como métodos abstratos.
2- Classe Automóvel
3- Classe Aeronave
Na classe Veiculo temos:
O modificador de acesso virtual indica que o método pode ser sobrescrito na classe derivada.
Na classe Automovel temos:
Na classe Aeronave temos:
Agora vamos definir o código para usar as classes e mostrar o comportamento de polimorfismo. Inclua o código abaixo na classe Program.cs no método Main():
using System; namespace CSharp_Polimorfismo1 { class Program { static void Main(string[] args) { Veiculo[] veiculo = new Veiculo[2]; veiculo[0] = new Automovel("Ferrari"); veiculo[1] = new Aeronave("Tucano"); MovimentarVeiculo(veiculo[0]); MovimentarVeiculo(veiculo[1]); Console.ReadKey(); } public static void MovimentarVeiculo(Veiculo veiculo) { Console.WriteLine(veiculo.Tipo); veiculo.Mover(); } } } |
|
No código cima temos :
- A criação de um vetor com dois
elementos;
- A criação de duas instâncias, uma de Automovel
e outra de Aeronave;
- A chamada do método MovimentarVeiculo que
simula o movimento para cada veiculo;
Observe que no método MovimentarVeiculo estamos usando o método Mover() para cada tipo de veiculo que foi instanciado e cada objeto sabe realizar o movimento correto em resposta à mesma chamada do método.
Aqui estamos usando o conceito de polimorfismo pois o método Mover() é executado e a decisão de qual movimento será usado ocorre em tempo de exeucução;
Usamos veiculo.Mover() ao invés de Aeronave.Mover() ou Automovel.Mover().
Para usar o polimorfismo os objetos precisam executar as mesmas ações (métodos) mesmo que possuam comportamento diferente.
Prática 2 - Polimorfismo com sobrecarga de métodos
Vamos incluir um novo projeto na solução criada no item.
Clique no menu File->Add->New Project e informe o nome Polimorfismo_SobrecargaMetodos;(Dessa forma teremos uma solução com dois projetos.)
Clique no menu Project->Add Class e informe o nome Calcular.cs e a seguir digite o código abaixo para a classe Calcular.
namespace Polimorfismo_SobrecargaMetodos { class Calcular { public int Soma(int num1, int num2) { return (num1 + num2); } public int Soma(int num1, int num2, int num3) { return (num1 + num2 + num3); } } } |
Agora digite o código abaixo no arquivo Program.cs :
using System; namespace Polimorfismo_SobrecargaMetodos { class Program { static void Main(string[] args) { Calcular calc = new Calcular(); Console.WriteLine("\nPolimorfismo com sobrecarga\n"); Console.WriteLine("Somando 2 números..."); Console.WriteLine(calc.Soma(45,43)); Console.WriteLine("Somando 3 números..."); Console.WriteLine(calc.Soma(45, 43, 100 )); Console.ReadKey(); } } } |
|
A sobrecarga de métodos é um conceito onde usamos o mesmo nome do método muitas vezes na mesma classe, mas cada método com parâmetros diferentes. Com base nos parâmetros passados a execução é decidida em tempo de compilação.
Uma outra forma (mais elegante e correta) de obter o mesmo resultado seria utilizando classes abstratas ou interfaces, mas isso é assunto para outro artigo...
Pegue o projeto completo aqui: CSharp_Polimorfismo1.zip
Rom 8:16
O Espírito mesmo testifica com o nosso espírito que somos filhos de Deus;
Rom 8:17 e, se filhos, também herdeiros, herdeiros de
Deus e co-herdeiros de Cristo; se é certo que com ele padecemos, para que
também com ele sejamos glorificados.
Rom 8:18 Pois tenho para mim que as aflições deste tempo presente não se podem comparar
com a glória que em nós há de ser revelada.
Referências: