Páginas

domingo, 1 de maio de 2011

Free Pascal - Variáveis Procedurais

Depois de um longo tempo afastado do blog, estamos retornando. Iremos iniciar uma série de artigos dedicados às estruturas de dados do Free Pascal. Mas antes de iniciar é necessário uma breve introdução a variáveis procedurais.
Variáveis procedurais ou tipos procedurais são um recurso do Free Pascal que permite armazenar métodos, funções e procedimentos em variáveis. Tais variáveis podem ser normalmente tratadas, passando-as como parâmetros e chamando os métodos quando for necessário.
Para exemplificar o uso deste recurso vejamos como declarar um tipo procedural:

type
  TFuncaoSemParametro = function(): String;
  TFuncaoComParametro = function(x: String): String;

O primeiro exemplo declara um tipo que armazena um função que não recebe argumentos. O segundo exemplo declara um tipo que armazena uma função que recebe parâmetros.
Tipos procedurais também podem ser declarados de mais duas maneiras, como pode ser visto abaixo. O primeiro declara um tipo para armazenar um procedimento e o segundo armazena um método de uma classe:

type
   TProcedimento = procedure;
   TMetodo = procedure of Object;

Prosseguindo então com nosso exemplo, em seguida iremos declarar as funções:

function AloMundo: String;
begin
  Result := 'Alo Mundo';
end;

function AloNovamente(S: String): String;
begin
  Result := 'Alo ' + S;
end;

Essas duas funções serão usadas como argumentos nas chamadas aos dois procedimentos seguintes, que recebem como parâmetros os tipos procedurais declarados.

procedure Primeiro(f: TFuncaoSemParametro);
begin
  WriteLn(f());
end;

procedure Segundo(f: TFuncaoComParametro);
begin
  WriteLn(f('Novamente'));
end;                 

Observe que tanto o procedimento Primeiro, quanto o procedimento Segundo executam a função que recebem como parâmetro. As funções chamadas irão retornar Strings que serão escritas no console através de writeln.
Para testar a funcionalidade apenas chame os procedimentos assim:

Primeiro(@AloMundo);
Segundo(@AloNovamente);

O símbolo @ converte a variável em um ponteiro. É desta forma que a função é passada como parâmetro.
É importante observar que o compilador verifica se a função ou o procedimento que está sendo passado como parâmetro corresponde exatamente ao esperado, ou seja, possui os mesmos parâmetros, o mesmo tipo de retorno, etc.
O mecanismo usado pelos eventos de componentes da biblioteca do Lazarus é exatamente este. Veja como pode ser criado um componente dinamicamente e como atribuir um método a um evento de um TButton no post Lazarus - Criando componentes em run-time.
A seguir o código completo da aplicação console:

program procvar;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes
  { you can add units after this };
type
  TFuncaoSemParametro = function(): String;
  TFuncaoComParametro = function(x: String): String;

function AloMundo: String;
begin
  Result := 'Alo Mundo';
end;

function AloNovamente(S: String): String;
begin
  Result := 'Alo ' + S;
end;

procedure Primeiro(f: TFuncaoSemParametro);
begin
  WriteLn(f());
end;

procedure Segundo(f: TFuncaoComParametro);
begin
  WriteLn(f('Novamente'));
end;

{$R *.res}

begin
  Primeiro(@AloMundo);
  Segundo(@AloNovamente);
  ReadLn;
end.

Atualizado em 03/05/2011.

2 comentários:

Gustavo Castelo Branco Avelar disse...

Olá Professor, estou criando uma aplicação em Lazarus e encontrei esse excelente blog sobre o mesmo e o estou seguindo, porém, estou tendo uma dúvida sobre formulários, é o seguinte: no form principal tem um menu com botões e um dos botões chama um outro formulário e dentro deste formulário(2) tem um botão fechar.Como faço quando clicar nesse botão fechar(que fecha o segundo formulário) e chamar o formulário principal?
Agradeço a atenção do Senhor e parabéns pelo blog.

Professor Carlos disse...

Gustavo

No primeiro botão você chama o segundo form usando o método show() ou showmodal(). O principal continua aberto, mas talvez oculto pelo seu segundo form. No segundo form, chame o método close() no botão fechar e pronto.

 
Creative Commons License
This work by Carlos Alberto P. Araújo is licensed under a Creative Commons Atribuição-Uso não-comercial-Compartilhamento pela mesma licença 3.0 Brasil License.