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;
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
Agradeço a atenção do Senhor e parabéns pelo blog.
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.