Quando estava preparando os exemplos de código para o artigo sobre ForIn para FireDAC, lembrei de um artigo do meu amigo Marcos Douglas publicado no Object Pascal Programming que discorre sobre a programação Imperativa ou Estruturada.

Na Ciência da Computação, programação imperativa é um paradigma de programação que descreve a computação como ações, enunciados ou comandos que mudam o estado (variáveis) de um programa. Muito parecido com o comportamento imperativo das linguagens naturais que expressam ordens, programas imperativos são uma sequência de comandos para o computador executar. (Wikipedia)

O artigo traz como objetivo discutir o fim do FreeAndNil propondo a utilização de Interface na programação PASCAL. Extraindo o conceito é possível escrever código utilizando diretamente interface o que demostra o poder da linguagem frente aos novos paradigmas.

Reescrevendo TFDQuery com interface, podemos fazer:

[code]
TQueryIntf.New(FDConnection1)
.Table(‘sigcad a’)
.FieldNames(‘codigo,nome’)
.Where(‘codigo between :codigo_de and :codigo_ate’)
.ParamValue(‘codigo_de’, 1)
.ParamValue(‘codigo_ate’,5)
.open
.DoQuery( procedure (ds:TDataset)
begin
memo1.Lines.Add( ‘Carregou: ‘+intToStr(ds.RecordCount) )
end);
[/code]

 

Recurso de loops com ForIn não estão disponível para os componentes TDataSet o que não permite usar:

[code lang=”pascal”]
var fld:TFields;
begin
for fld in FQuery1 do
begin
memo1.lines.add( fld.fieldByName(‘nome’).asString );
end;
end;
[/code]

Um objeto que queira fazer uso de ForIn deve implementar a interface IEnumerator.
Fazendo uma adaptação útil para a classe TFDQuery do FireDAC é possível escrever os seguintes métodos para atender a condição do ForIn:

[code lang=”pascal”]
    function GetEnumerator: IQuery;
    function GetCurrent: TFields;
    property Current:TFields read GetCurrent;
    function MoveNext: boolean;
    procedure Reset;
[/code]

Código Fonte no Git

A propriedade de colunas da tabela já implementa Enumerator o que permite usar:

[code lang=”pascal”]
for f in query1.fields do
begin
memo1.Lines.add( f.FieldName );
end;
[/code]