quinta-feira, 8 de novembro de 2007

Polimorfismo não é bicho de sete cabeças!

É interessante como a POO em geral é um paradigma para muitos. Depois de muitos anos já se falando sobre o assunto, muitos ainda a tratam como um "TABÚ".
Normalmente, aqueles que "nasceram" na programação estruturada tem uma dificuldade maior para entender o conceito (ou filosofia, como alguns gostam de chamar).

Mas o fato é que não existe nenhum mistério, e posso garantir que os benefícios são muitos. E das possibilidades apresentadas pela POO, sem dúvida a que mais me fascina é o POLIMORFISMO.

A descrição mais usada para ele é a possibilidade que determinado objeto tem para assumir comportamentos diferentes dependendo da necessidade.

Eu vou exemplificar aqui os benefícios e ao mesmo tempo mostrar que não existe nenhum bicho de sete cabeças no polimorfismo.

Abra um novo projeto no delphi, salve com o nome de Polimorfismo.dpr, o form com o nome de uFrmMain.

Vamos incluir uma nova unit para criar a nossa classe. Para isso vá em File/New/Unit salve com o nome de uCalculadora e implemente a unit como a listagem abaixo:

unit uCalculadora;

interface

uses SysUtils;

type
TCalculadora = class
public

function Calcular (ValueA, ValueB:Real): Real; virtual; abstract;
end;

TMultiplicar = class(TCalculadora)
public
function Calcular (ValueA, ValueB:Real): Real; override;
end;

TSomar = class(TCalculadora)
public
function Calcular (ValueA, ValueB:Real): Real; override;
end;

TSubtrair = class(TCalculadora)
public
function Calcular (ValueA, ValueB:Real): Real; override;
end;

TDividir = class(TCalculadora)
public
function Calcular (ValueA, ValueB:Real): Real; override;
end;

implementation

{ TMultiplicar }

function TMultiplicar.Calcular(ValueA, ValueB: Real): Real;
begin
Result := ValueA * ValueB;
end;

{ TSomar }

function TSomar.Calcular(ValueA, ValueB: Real): Real;
begin
Result := ValueA + ValueB;
end;

{ TSubtrair }

function TSubtrair.Calcular(ValueA, ValueB: Real): Real;
begin
Result := ValueA - ValueB;
end;

{ TDividir }

function TDividir.Calcular(ValueA, ValueB: Real): Real;
begin
try
Result := ValueA / ValueB;
except on E: Exception do
begin
if Pos('BY ZERO', UpperCase(E.Message)) > 0 then
Raise Exception.Create('Não é permitido divisão por zero.');
end;
end;
end;

end.


Primeiro criamos uma classe com o nome de TCalculadora com um método chamado Calcular, observe a que definimos o método com o tipo virtual e com a diretiva abstract indicando que o método não será implementado na classe em que foi declarado.

Em seguida criamos 4 classes (TMultiplicar, TSomar, TSubtrair, TDividir) , todos elas descendem de TCalculadora e tem o método calcular (exatamente igual ao método da classe TCalculadora) com a diretiva override (sebrecarga) garantindo que o método tenha apenas a implementação da classe descendente sobrepondo a implementação da classe base.

Depois implementamos o método de cada classe conforme a operação. Agora vamos criar o exemplo de utilização dessas classes.

No FrmMain coloque os seguintes componentes: 3 Edits; 1 Button e um RadioGroup.
Adicione ao RadioGroup 3 itens (Somar, Multiplicar, Subtrair,Dividir), altere a propriedade ItemIndex para 0 (Zero).

Posicione os componentes conforme a figura abaixo:


Implemente o botão calcular conforme a listagem abaixo:

procedure TFrmMain.Button1Click(Sender: TObject);
var
Calculadora: TCalculadora;
begin
case RadioGroup1.ItemIndex of
0: Calculadora := TSomar.Create;
1: Calculadora := TMultiplicar.Create;
2: Calculadora := TSubtrair.Create;
3: Calculadora := TDividir.Create;
end;
Edit3.Text := FloatToStr(Calculadora.Calcular(StrToFloatDef(Edit1.text,0),StrToFloatDef(Edit2.text,0)));
end;


Criamos uma variável com o tipo da nossa classe base (TCalculadora) depois CRIAMOS com o tipo da classe descendente correspondente a operação que desejamos. Percebam que chamamos o método Calcula do nosso objeto sem nos preocupar com a implementação.

Download do exemplo


Como vocês podem ver não existem mistérios! não deixem de comentar esse post! até a próxima!




5 comentários:

Unknown disse...

Cristiano este foi o artigo mais esclarecedor que li sobre o assunto até o momento.

Obrigado e parabens.

Baladeva, WebMaster do Portal Lucadosa. disse...

Cristiano, sou Borland Certified Professional Delphi 7, e desenvolvo com esta ferramenta a 10 anos, e tenho 22 anos na área. Achei o seu artigo claro, fácil e objetivo, parabéns, vou indicar para alguns amigos a sua orientação, pois como não tenho muito tempo pra ajudá-los, decidi procurar algo que fale de OO e Delphi e o seu artigo sobre o Polimorfismo é ótimo.

Grande abraço.

Luis Carlos.

Cristiano Martins Alves disse...

Olá Luis, obrigado pelas palavras, confesso que estou em dívida com o Blog, mas com toda a certeza é muito recompensador quando temos o nosso trabalho reconhecido.

Unknown disse...

Beleza de artigo eu só tracaria o nome da classe base para TOperacao e chamaria o método de Execute. É mais condizente com o que as classes propoem. O TCalculadora poderia ser uma segunda classe que tivesse metodos para cada operacao.
Assim vc instancia a calculadora e chama Calculadora.Dividir(...).

Valeu, mas beleza de artigo

Leo Vip disse...

Cara Parabéns muito bom o melhor esclarecimento que li sobre polimorfismo, fiquei intrigado pq me disseram q o delphi não fazia isso como não? Está aí Parabéns.