POO - Polimorfismo
Olá a todos. Este é outro post falando das técnicas de programação orientada a objetos.
Polimorfismo é a técnica que permite implementar um método numa classe que tenha o comportamento diferente do método na sua classe ancestral. Podemos entender como um exemplo um objeto chamado Automóvel, que tem dois descendentes: Carro e Moto.
O Objeto Automóvel tem um método chamado ligar, que todo automóvel possui. Os objetos Carro e Moto também têm o método ligar, porém com implementações diferentes entre si.
Vamos fazer alguns códigos:
Delphi:
interface type TAutomovel = class public procedure Ligar; end; TCarro = class(TAutomovel) public procedure Ligar; override; end; TMoto = class(TAutomovel) public procedure Ligar; override; end; implementation procedure TAutomovel.Ligar; begin {implementação do método Ligar da classe TAutomovel} end; procedure TCarro.Ligar; begin {a palavra chave inherited indica que este método vai incluir a implementação do método do ancestral no ponto em que foi inserida} inherited; {implementação do método Ligar da classe TCarro} end; procedure TMoto.Ligar; begin {a palavra chave inherited indica que este método vai incluir a implementação do método do ancestral no ponto em que foi inserida} inherited; {implementação do método Ligar da classe TMoto} end;
Java:
class Automovel { pubic void ligar() { // implementação do método ligar da classe Automovel } } class Carro extends Automovel { public void ligar() { // o método super() chama a implementação do método da classe // ancestral no ponto em que foi iserido super(); // implementação do método ligar da classe Carro } } class Moto extends Automovel { public void ligar() { // o método super() chama a implementação do método da classe // ancestral no ponto em que foi iserido super(); // implementação do método ligar da classe Moto } }
C#
class Automovel { public void ligar() { // implementação do método ligar da classe Automovel } } class Carro : Automovel { public override void ligar() { // a chamada a base.chama a implementação do método da classe
// ancestral no ponto em que foi iserido
base.ligar();
// implementação do método ligar da classe Carro
}
}
class Moto : Automovel {
public override void ligar() {
// a chamada a base.chama a implementação do método da classe
// ancestral no ponto em que foi iserido
base.ligar();
// implementação do método ligar da classe Moto
}
}
Outra forma de polimorfismo é quando a classe ancestral tem um método mas não faz nenhuma implementação, deixando-a por parte das suas classes descendentes. Este tipo de método é chamado abstrato. Neste caso a classe derivada é obrigada a fazer sua própria implementação do método.
Vou abrir um pequeno parêntesis para falar sobre 'abstratos' em POO.
Geralmente métodos e classes abstratas apenas repredentam a idéia e não a funcionalidade. Vamos a exemplos:
Classes abstratas não podem ser instanciadas.
O quê? Como assim? Por que ter classe se eu não posso instanciá-la?
Uma das principais vantagens de se usar classes abstratas é que nos permite introduzir comportamento comum aos descendentes.
Vamos a um exemplo prático: Figuras geométricas. O que é exatamente uma figura geométrica? Nós não temos uma resposta concreta porque figura geométrica é um objeto abstrato. Mas quanto a quadrado? Retângulo? Losango? Estes são figuras geométricas que podemos descrever claramente.
Todas as figuras geométricas têm um método chamado 'desenhar', mas as implementações são diferentes entre as figuras. É aí que entram a classe abstrata e o método abstrato.
Classes abstratas não podem ser instanciadas. Por um motivo bem simples: Porque são abstratas! Hehe... A classe só tem uma estrutura básica para servir de base para as suas classes descendentes.
Por exemplo, a classe FiguraGeometrica tem o método abstrato Desenhar, que aceita como argumentos as coordenadas de onde ele vai começar a ser desenhado (x e y). Todos os seus descendentes terão este método, mas cada um deles deve ter sua própria implementação.
Delphi
type
TFiguraGeometrica = class
public
procedure Desenhar(const x, y: Integer); virtual;
end;
TQuadrado = class(TFiguraGeometrica)
public
procedure Desenhar(const x, y: Integer); override;
end;
TLosango = class(TFiguraGeometrica)
public
procedure Desenhar(const x, y: Integer); override;
end;
...
procedure MontarFigura(Figura: TFiguraGeometrica; const x, y: Integer);
begin
Figura.Desenhar(x, y);
end;
Java
abstract class FiguraGeometrica {
abstract void desenhar(int x, int y);
}
class Quadrado extends FiguraGeometrica {
public void desenhar(int x, int y) {
// implementação do método desenhar do objeto Quadrado
}
}
class Losango extends FiguraGeometrica {
public void desenhar(int x, int y) {
// implementação do método desenhar do objeto Losango
}
}
...
void montarFigura(FiguraGeometrica figura, int x, int y) {
figura.desenhar(x, y);
}
C#
abstract class FiguraGeometrica {
public abstract void desenhar(int x, int y);
}
class Quadrado : FiguraGeometrica {
public override void desenhar(int x, int y) {
// implementação do método desenhar do objeto Quadrado
}
}
class Losano : FiguraGeometrica {
public override void desenhar(int x, int y) {
// implementação do método desenhar do objeto Losango
}
}
...
public void montarFigura(FiguraGeometrica figura, int x, int y) {
figura.desenhar(x, y);
}
Mas Felipeeee... que efeito prático isso vai ter na aplicação?
Desta forma nós evitamos redundância no nosso código, 'if' que não precisamos... Quando executamos o método MontarFigura nós passamos qualquer objeto derivado da classe FiguraGeometrica que, pelo fato dela ser abstrata (virtual em delphi) ela vai executar o método da classe derivada correspondente. Maneiro, né...
Esse post acabou sendo mais longo que eu esperava, mas espero que o conteúdo postado tenha sido bem absorvido. Abraços.
Guri vlw, amanhã eu tenho Avaliação de POO na facul, e vc me ajudou bastante a entender Polimorfismo!
ResponderExcluirmuito obrigada!