sexta-feira, 23 de março de 2007

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.

Um comentário:

  1. Guri vlw, amanhã eu tenho Avaliação de POO na facul, e vc me ajudou bastante a entender Polimorfismo!

    muito obrigada!

    ResponderExcluir

 
BlogBlogs.Com.Br