Olá pessoal, neste artigo vou demonstrar como trabalhar com functions e procedures no Delphi, passando por definições, tipos de parâmetros de entrada, chamadas e etc.

Esse artigo é destinado para o leitor iniciante em Delphi, geralmente existe sempre a dúvida de como trabalhar com essas sub-rotinas. Para os leitores que tem conhecimento em Java ou C#, pode ser estranho esse termo procedure e function pois nessas linguagens existem somente chamada à métodos que podem ou não retornar valores, para diferenciar basta usar a palavra reservada void na assinatura do método, que indica que tal método não retorna valor. Já no Object Pascal linguagem base do Delphi existem várias definições diferentes em literaturas e na internet, mas em particular gosto de usar essa:

  • PROCEDURE: Sub-rotina que processa informações e não retorna valor.
  • FUNCTION: Sub-rotina que processa informações e retorna um valor.

Sintaxe

Uma function pode receber nenhum, um ou vários parâmetros de entrada e retornar um determinado valor, vamos a sintaxe básica aperesentada na Listagem 1.


Function NomeFunção(Parâmetro1:Tipo;Parâmetro2:Tipo): Tipo de Retorno;
Var
  {declaração de variáveis se necessário}
Begin
{Instruções}
//Para retornar o valor desejado podemos usar a palavra reservada Result.
Result := Valor de Retorno;

//ou o nome da função.
NomeFunção := Valor de Retorno;
End;
Listagem 1. Sintaxe de um Function

Um Procedure pode receber nenhum, um ou vários parâmetros de entrada mas não retorna nenhum tipo de valor, salvo exceções que explicaremos mais adiante. Observe a Listagem 2.


procedure NomeProcedure(Parâmetro1:Tipo;Parâmetro2:Tipo);
Var
  {declaração de variáveis se necessário}
Begin
{Instruções}
End;
Listagem 2. Sintaxe de um Procedure

Exemplos

Vamos ao exemplo de uma função muito popular na internet para somar dois valores inteiros e retornar um valor inteiro. Notem que essa função receberá dois parâmetros do tipo integer e retornar a soma que é do tipo integer, como mostra a Listagem 3.


function Soma(a, b: integer): integer;
begin
    //Retorna o valor da soma a + b.
    Result := a + b;
end; 
Listagem 3. Função para somar 2 valores e retornar o valor da soma

Agora um exemplo na Listagem 4 de procedure que receberá um valor inteiro e verificar se esse valor é par ou ímpar, ao final emite uma mensagem na tela.


procedure VerificaParImpar(a: integer);
begin
    if a mod 2 = 0 then
        ShowMessage('Número par!')
    else
        ShowMessage('Número Ímpar!');
end; 
Listagem 4. Procedure para verificar se o valor é par ou ímpar

Notem que a procedure emite uma mensagem avisando se o valor é par ou ímpar, essa mensagem não pode ser considerada com um valor de retorno mas sim parte das instruções de processamento das informações. Já no caso da function ela processa a soma de a + b e retorna o valor da soma, podemos atribuir esse valor a um determinado componente ou variável, na procedure não podemos executar esse tipo de atribuição, pois ela não possui valor de retorno.

Parâmetros

Como já foi mencionado, se necessário podemos passar parâmetros para functions e procedures, esses parâmetros podem ser por valor ou referência.

Valor

Nos dois exemplos acima foram passados parâmetros por valor, ou seja, internamente no compilador será preenchido o parâmetro que está entre parênteses com uma cópia do valor de origem, para que esse valor seja usado dentro da function ou procedure, mas o valor original não será alterado. Observe a Listagem 5 e o resultado na Figura 1.


procedure TForm1.btn1Click(Sender: TObject);
var
  a, b: Integer;
begin
    //Inicia "a" com valor 1
    a := 1;
    //Variável "b" recebe o valor de retorno da função SomaValor passando a variável "a" como parâmetro.
    b := SomaValor(a);
    //Emite mensagem com os valores
    ShowMessage('Valor de (a) antes chamada da função: ' + IntToStr(a) + #13 +
                'Valor de (b) após chamada da função: ' + IntToStr(b)  + #13 +
                'Valor de (a) após chamada da função: ' + IntToStr(a));
end;

function TForm1.SomaValor(x: integer): Integer;
begin
     //Adiciona 1000 ao valor de a
     x := x + 1000;
     //Retorna o valor de a
     Result := x;
end;
Listagem 5. Exemplo de parâmetro por valor
Mensagem exibindo os valores das variáveis “a” e “b”
Figura 1. Mensagem exibindo os valores das variáveis “a” e “b”

Notem que não houve alteração no valor da variável “a” mesmo após a chamada da função, isso porque o valor de “a” foi copiado para o parâmetro “x” da função SomaValor, sendo assim podemos alterar valores de x porque ela não tem vínculo com a variável a.

Referência

Podemos modificar esse contexto se utilizarmos na assinatura da function antes do nome do parâmetro a palavra reservada “var”, isso indica que será passado o endereço da variável a como parâmetro e não mais a cópia do valor como anteriormente. Desse modo toda e qualquer alteração no valor de x dentro da function será revertida para variável a, como mostra a Listagem 6 e o resultado na Figura 2.


function TForm1.SomaValor(var x: integer): Integer;
begin
     //Adiciona 1000 ao valor de a
     x := x + 1000;
     //Retorna o valor de a
     Result := x;
end;
Listagem 6. Exemplo de parâmetro por referência
Mensagem exibindo os valores das variáveis “a” e “b”, usando “var”
Figura 2. Mensagem exibindo os valores das variáveis “a” e “b”, usando “var”

Nesse exemplo utilizamos uma function, também poderíamos usar sem problemas uma procedure até porque não retornamos valor mas sim alteramos o valor da variável “a”, isso porque passamos o endereço dessa variável como parâmetro. Ainda usando “var” podemos passar qualquer tipo objeto como referência desde componentes da VCL até objetos instanciados a partir de classes criadas por nós mesmos.

Existe outra situação muito interessante nos parâmetros das procedures que podemos usar com muita eficiência, no início do artigo mencionei que uma “procedure não retorna nenhum tipo de valor, salvo exceção”. Essa exceção se aplica ao uso da palavra reservada “out”. Quando declararmos a palavra “out” antes do parâmetro, estamos indicando que ele vai receber um valor de saída da procedure, mas alguns leitores podem se questionar “Procedure não retorna valores!”, é verdade mas nesse caso estamos declarando que esse parâmetro que nada mais é que uma referência a uma variável, vai receber um determinado valor após o processamento interno da procedure e consequentemente podemos acessá-lo após a chamada da procedure, acompanhem o exemplo da Listagem 7 e Figura 3.


procedure TForm1.btn3Click(Sender: TObject);
var
   a, retorno: Integer; //variável "retorno" para capturar o retorno da procedure
begin
    //Atribui 1 para variável "a"
    a := 1;
    //Chama a procedure SomaValor2 e passa como parâmetro a variável "a"
    //e como parâmetro de saída variável "retorno"
    SomaValor2(a,retorno);
    //Emiti mensagem com o valor da variável "retorno"
    ShowMessage('Valor da variável (retorno): ' + IntToStr(retorno));
end;

procedure TForm1.SomaValor2(x: integer; out saida: Integer);
begin
     //Adiciona 1000 ao valor de "x"
     x := x + 1000;
     //Atribui o valor de "x" ao parâmetro saída que foi declarado como "out"
     saida := x;
end; 
Listagem 7. Exemplo de parâmetro “out”
Mensagem exibindo o valor da variável “retorno” usando “out”
Figura 3. Mensagem exibindo o valor da variável “retorno” usando “out”

Notem que antes de chamarmos a procedure com parâmetro “out” de retorno temos que declarar uma variável do mesmo tipo do parâmetro, essa variável vai receber o resultado da procedure, caso fosse atribuído algum valor para variável “retorno” antes da chamada da procedure esse valor seria desprezado.

Declaração

No Delphi todas as procedures e functions são declaradas na seção interface, o programador define o escopo da função private, public são os mais utilizados, segue na Listagem 8 o exemplo da declaração das functions e procedures desse artigo.


unit UPrincipal;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    btn1: TButton;
    btn2: TButton;
    btn3: TButton;
    procedure btn1Click(Sender: TObject);
    procedure btn3Click(Sender: TObject);
  private
    function SomaValor(x: integer): Integer;
    function SomaValorRef(var x: integer): Integer;
    procedure SomaValor2(x: integer; out saida: Integer);  
public
    { Public declarations }
  end; 
Listagem 8. Declaração das functions e procedures

Podemos ainda declarar uma function ou procedure dentro de outra procedure, lembrando que ela só será visível dentro da procedure de origem, semelhante a escopo das variáveis declaradas dentro das procedures só ficam visíveis internamente. Desse modo não é necessário declarar na seção interface, como mostra a Listagem 9 e Figura 4.


procedure TForm1.btn4Click(Sender: TObject); //Procedure principal
  //Declaração interna da function
  function Somar(a, b: integer): Integer;
  begin
      Result := a + b;
  end;

var
   resultado: Integer;
begin
    //Chamando function interna
    resultado := Somar(10, 20);
    ShowMessage('Valor da soma: ' + IntToStr(resultado));
end;
Listagem 9. Declaração das functions e procedures dentro de outra procedure
Mensagem utilizando function dentro da procedure
Figura 4. Mensagem utilizando function dentro da procedure

Chamadas

Para chamar uma function ou procedure é muito simples, no caso da function basta digitar o mesmo nome da assinatura da mesma, sendo precedida ou não de parênteses, depende da necessidade de passar parâmetros, atribuir o valor de retorno para uma variável do mesmo tipo de retorno da function, como mostra a Listagem 10.


var
   resultado: Integer;
begin
    //Chamando function, passa os parâmetros e atribui o valor de retorno
    resultado := Somar(10, 20);
    ShowMessage('Valor da soma: ' + IntToStr(resultado));
end;
Listagem 10. Chamada de uma function

No caso da procedure, como não existe um valor de retorno basta digitar o mesmo nome da assinatura da mesma, sendo precedida ou não de parênteses, depende da necessidade de passar parâmetros, como mostra a Listagem 11.


begin
    //Chamando procedure com parênteses.
    EmitirMensagem();
    ou
    //Chamando procedure sem parênteses.
    EmitirMensagem;
end;
Listagem 11. Chamada de uma procedure

Bom pessoal, demonstrei nesse artigo princípios básicos de functions e procedures. Como o nosso Delphi difere alguns conceitos em relação à algumas linguagens como Java e C#, é sempre bom pegar essas dicas principalmente para quem está chegando no Delphi.

Espero que tenham apreciado esse artigo e até a próxima.

Abraço...