Baixe o app para aproveitar ainda mais
Prévia do material em texto
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.Agora sim, nada mal, hein? Sem nenhum "IF" e nada nesta manga e nem nesta outra. :-) Incrementar a calculadora agora se resume à ampliar o tipo enumerado, criar um novo método que faça a operação em si e alimentar o nosso vetor. Conclusão --------- A arte de programar não se resume à saber o que é um "if, then, else", um "array" e outras palavras-chave. Também, um código extenso pode, muitas vezes, ser reduzido e simplificado se você dominar os recursos oferecidos pela linguagem. Esse domínio deveria sempre se fazer presente a tal ponto dos recursos da linguagem não serem apenas como ilhas isoladas, mas sim como engrenagens que, juntas, impulsionam a verdadeira força de um sistema bem estruturado e expansível. Este artigo demonstra como idéias triviais e de conhecimento geral podem, unidas e em igual quantidade, reduzir a manutenção e aumentar a capacidade de expansão de um sistema. Até a próxima, Italo Gomes (aka MerriT) Master em Delphi pela Brainbench www.brainbench.com
Compartilhar