Logo Passei Direto

A maior rede de estudos do Brasil

Grátis
4 pág.
Truques Espertos Pascal

Pré-visualização | Página 1 de 2

Introdução
----------
Bem, preciso escolher um tipo simples que todos conheçamos para que possamos explorá-lo nesse artigo. Hummm... ok, arrays.
Você conhece os arrays? Estou certo que sim. O conceito de vetores é um dos mais antigos e, por conseguinte, comuns nas linguagens de programação. A questão importante aqui é: você sabe MESMO como explorar a versatilidade dos vetores?
Este artigo se propõe a demonstrar como a simples utilização de vetores com outros tipos comuns do Delphi podem lhe poupar MUITAS linhas de código.
O básico a saber
----------------
Antes de começarmos é interessante darmos uma olhada em um tipo particular do Pascal chamado tipo enumerado. Mesmo que esse nome lhe pareça estranho, você certamente já o usou até mesmo no Object Inspector.
Trocando em miúdos, um tipo enumerado é uma mera representação textual, sequencial e limitada de um valor inteiro, cujo limite ordinal (ou seja, sua representação numérica) está definido entre [0, 255]. 
De fato, a utilização de tipos enumerados torna a programação muito mais legível e elegante porque, ao invés de usarmos números e/ou constantes inteiras, usamos valores pré-definidos e textuais. Além disso, tipos enumerados nos permitem alguns truques com o assunto em pauta: vetores. Mas isso fica para daqui à pouco.
Por enquanto vamos dar um exemplo de um tipo enumerado, que se chamará TOperacaoAritmetica. Conforme formos elaborando o exemplo final, a utilidade deles ficará mais evidente.
Fixação de conceitos
--------------------
Clique em File / New Application. Na seção "type" da Unit1, declare o tipo abaixo:
type
TOperacaoAritmetica = (oaSomar, oaSubtrair, oaMultiplicar, oaDividir);
TForm1 = class(TForm)
(...)
Esse tipo define uma sequência de valores enumerados. Variáveis desse tipo só podem receber um valor que esteja dentro daquele conjunto definido.
Ora, vejamos então se podemos utilizar a característica delimitadora de um tipo enumerado para algo mais sofisticado. 
Seria útil podermos ter uma representação em string do que cada valor de TOperacaoAritmetica representa, pois não? Então, inclua o novo tipo abaixo:
type
TOperacaoAritmetica = (oaSomar, oaSubtrair, oaMultiplicar, oaDividir);
TOperacoesAritmeticas = array[TOperacaoAritmetica] of string;
TForm1 = class(TForm)
(...)
Parece interessante! Temos agora um tipo que define um vetor cujo tamanho e indexação é um tipo enumerado. O que significa que podemos acessar os itens do vetor usando valores enumerados. Antes de usarmos isso à nosso favor, vamos definir um vetor constante que contém as referidas strings:
type
TOperacaoAritmetica = (oaSomar, oaSubtrair, oaMultiplicar, oaDividir);
TOperacoesAritmeticas = array[TOperacaoAritmetica] of string;
const
OPERACOES_ARITMETICAS: TOperacoesAritmeticas = ('Somar', 'Subtrair', 'Multiplicar', 'Dividir');
type
TForm1 = class(TForm)
(...)
Precisamos de algo que torne visível o efeito aplicado no vetor. Em sendo assim, adicione um TRadioGroup no Form1 (RadioGroup1). No evento OnCreate do Form1, adicione o código a seguir:
procedure TForm1.FormCreate(Sender: TObject);
var
Index: TOperacaoAritmetica;
begin
for Index := Low(OPERACOES_ARITMETICAS) to High(OPERACOES_ARITMETICAS) do
RadioGroup1.Items.Add(OPERACOES_ARITMETICAS[Index]);
end;
Nada mal, hein? Um looping definido por um tipo enumerado, um vetor indexado pelo mesmo tipo enumerado e, ainda, um RadioGroup preenchido automaticamente com apenas 3 linhas de código.
Ok, ok, nada de fantástico. Mas o melhor ainda está por vir.
Indo além: vetores de métodos
-----------------------------
Sim, isso mesmo - vetores de métodos. Não se impressione, a coisa é mais simples que parece.
Um vetor pode conter qualquer valor ou tipo simples conhecido pelo Delphi. Um deles são os registros. Em sendo um método um registro composto de 2 ponteiros - um para código e outro para dados (isso é assunto para outro artigo) - é natural que possamos guardar esses "registros" em um vetor. Vejamos como isso é possível.
Primeiro, declare um tipo que usaremos para definir como será um método nosso:
type
TOperacaoAritmetica = (oaSomar, oaSubtrair, oaMultiplicar, oaDividir);
TOperacoesAritmeticas = array[TOperacaoAritmetica] of string;
TMetodoOperacao = function(Arg1, Arg2: Integer): Integer of object;
const
OPERACOES_ARITMETICAS: TOperacoesAritmeticas = ('Somar', 'Subtrair', 'Multiplicar', 'Dividir');
type
TForm1 = class(TForm)
(...)
"TMetodoOperacao" simplesmente define como devem ser as funções que seguem àquele tipo. Tais funções devem receber dois argumentos, "Arg1" e "Arg2", e retornar um valor inteiro.
Falta agora definir como deverá ser nosso vetor de métodos:
type
TOperacaoAritmetica = (oaSomar, oaSubtrair, oaMultiplicar, oaDividir);
TOperacoesAritmeticas = array[TOperacaoAritmetica] of string;
TMetodoOperacao = function(Arg1, Arg2: Integer): Integer of object;
TMetodosOperacao = array[TOperacaoAritmetica] of TMetodoOperacao;
const
OPERACOES_ARITMETICAS: TOperacoesAritmeticas = ('Somar', 'Subtrair', 'Multiplicar', 'Dividir');
type
TForm1 = class(TForm)
(...)
Deve ser fácil compreender o tipo TMetodosOperacao uma vez que ele é bem semelhante, em funcionalidade e indexação ao TOperacoesAritmeticas.
Ok, já temos um tipo que define um vetor de métodos. Ainda temos que declarar o vetor propriamente dito para "guardar" os métodos a fim de que nossa brincadeira fique completa. 
Declare os seguintes métodos na seção "private" do Form1:
(...)
private
{ Private declarations }
function Somar(Arg1, Arg2: Integer): Integer;
function Subtrair(Arg1, Arg2: Integer): Integer;
function Multiplicar(Arg1, Arg2: Integer): Integer;
function Dividir(Arg1, Arg2: Integer): Integer;
(...)
A implementação deles é óbvia:
function TForm1.Somar(Arg1, Arg2: Integer): Integer;
begin
Result := Arg1 + Arg2;
end;
function TForm1.Subtrair(Arg1, Arg2: Integer): Integer;
begin
Result := Arg1 - Arg2;
end;
function TForm1.Multiplicar(Arg1, Arg2: Integer): Integer;
begin
Result := Arg1 * Arg2;
end;
function TForm1.Dividir(Arg1, Arg2: Integer): Integer;
begin
Result := Arg1 div Arg2;
end;
Declare agora um atributo privado que será, de fato, um vetor de métodos. Assim:
(...)
private
{ Private declarations }
FMetodosOperacao: TMetodosOperacao;
function Somar(Arg1, Arg2: Integer): Integer;
function Subtrair(Arg1, Arg2: Integer): Integer;
(...)
Ora, é claro que precisamos preenchê-lo para que possamos usá-lo, pois não? Inclua o código abaixo no evento OnCreate do seu Form1:
procedure TForm1.FormCreate(Sender: TObject);
var
Index: TOperacaoAritmetica;
begin
for Index := Low(OPERACOES_ARITMETICAS) to High(OPERACOES_ARITMETICAS) do
RadioGroup1.Items.AddObject(OPERACOES_ARITMETICAS[Index]);
FMetodosOperacao[oaSomar] := Somar;
FMetodosOperacao[oaSubtrair] := Subtrair;
FMetodosOperacao[oaMultiplicar] := Multiplicar;
FMetodosOperacao[oaDividir] := Dividir;
end;
Consolidando conhecimentos
--------------------------
Para que nosso exemplo fique completo e as idéias façam sentido juntas, vamos montar a nossa calculadora inteligente. 
Adicione 3 TEdit's e dê os nomes "EdtArg1", "EdtArg2" e "EdtResultado" para eles; alinhe-os um abaixo do outro. Coloque também um TButton (Button1) com o Caption igual à "Calcular".
No evento OnClick do Button1, coloque o código abaixo:
procedure TForm1.Button1Click(Sender: TObject);
var
Arg1, Arg2: Integer;
Resultado: Integer;
OperacaoAritmetica: TOperacaoAritmetica;
begin
Arg1 := StrToInt(EdtArg1.Text);
Arg2 := StrToInt(EdtArg2.Text);
OperacaoAritmetica := TOperacaoAritmetica(RadioGroup1.ItemIndex);
Resultado := FMetodosOperacao[OperacaoAritmetica](Arg1, Arg2);
EdtResultado.Text := IntToStr(Resultado);
end;
Salve o projeto e execute a aplicação. Digite dois números inteiros, um em EdtArg1 e outro em EdtArg2. Escolha a operação desejada no RadioGroup e clique no botão Calcular.
Página12