segunda-feira, 18 de outubro de 2010

Forward Declarations

Imagine que você está escrevendo uma biblioteca de funções estáticas em um arquivo .pas e precisa declarar o cabeçalho de uma função para que ela possa ser usada abaixo globalmente, mas você não quer colocar o cabeçalho na seção interface para que a função não seja publicada para todas as units, você quer manter ela em "segredo" na seção de implementation.

Você pode dizer: "simples, basta declarar a função inteira acima e pronto." Mas e se essa função precisa usar outra que também será declarada dessa maneira e vice-versa?

A solução é foward declaration. Tudo bem, não se usa muito hoje em dia, ainda mais em POO, mas segue abaixo um exemplo de como você pode declarar uma função adiando a sua real implementação "mais para baixo" mesmo na seção implementation:

unit uSomaForward;

interface

function SomaPublica(x, y: Integer): Integer;

implementation


function SomaPrivada(x,y: Integer): Integer; forward;

function SomaPublica(x, y: Integer): Integer;
begin
  Result := SomaPrivada(x, y);
end;


function SomaPrivada(x,y: Integer): Integer;
begin
  Result := x+y;
end;


end.
 

Esse você testa com:

ShowMessage(IntToStr(SomaPublica(5,9))); 

Vamos fazer uma brincadeira mais complexa: todo mundo sabe fazer uma função fatorial recursiva certo? E se dividíssemos a função em duas recursivas circulares que hora chama uma e hora chama outra? Lógico que não teremos isso na vida real, mas você pode ter dois métodos um fazendo chamada ao outro de maneira circular por n motivos, desde tratamento de arvores de menus até mesmo descuido e desatenção. Isso não vem ao caso, queremos apenas demonstrar como as foward declarations podem ajudar a resolver quebra-cabeças de funções auto referenciaveis que ainda não foram declaradas. Sem elas não seria possível uma função chamar a outra sem os cabeçalhos, experimente.

A função fatorial dependente de duas recursivas ficaria assim:

unit uInterdependentes;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils;

function FatorialChamanoFuncoesRecursivasInterDependentes(numero: integer):integer;



implementation

   function InterDependente(contador: integer): integer forward;
   function DependenteInter(contador: integer): integer forward;

   function FatorialChamanoFuncoesRecursivasInterDependentes(numero: integer):integer;
   begin
        Result :=  InterDependente(numero);
   end;

   function InterDependente(contador: integer): integer;
   begin
        if contador <= 1 then
        begin
             Result := 1;
        end
        else
        begin
            Result := contador * DependenteInter(contador-1);
        end;
   end;

   function DependenteInter(contador: integer): integer;
   begin
        if contador <= 1 then
        begin
             Result := 1;
        end
        else
        begin
            Result := contador * InterDependente(contador-1);
        end;
   end;

end.  
E você pode testar assim:
     ShowMessage(IntToStr(FatorialChamanoFuncoesRecursivasInterDependentes(5)));  //retornará 120

Até a próxima ;)

Nenhum comentário:

Postar um comentário

Postagens populares

Marcadores

delphi (60) C# (31) poo (21) Lazarus (19) Site aos Pedaços (15) sql (13) Reflexões (10) .Net (9) Humor (9) javascript (9) ASp.Net (8) api (8) Básico (6) Programação (6) ms sql server (5) Web (4) banco de dados (4) HTML (3) PHP (3) Python (3) design patterns (3) jQuery (3) livros (3) metaprogramação (3) Ajax (2) Debug (2) Dicas Básicas Windows (2) Pascal (2) games (2) linguagem (2) música (2) singleton (2) tecnologia (2) Anime (1) Api do Windows (1) Assembly (1) Eventos (1) Experts (1) GNU (1) Inglês (1) JSON (1) SO (1) datas (1) developers (1) dicas (1) easter egg (1) firebird (1) interfaces (1) introspecção (1) memo (1) oracle (1) reflexão (1)