Tanto o Free Pascal Compiler (FPC) quanto o CodeGear Delphi possuem suporte a generics, as extensões que permitem definir quais tipos de dados serão usados por classes ou funções (por exemplo) no momento de sua declaração. Hoje há uma tendência da adoção de generics em praticamente todas as linguagens OO. C++ tem seus templates desde o ISO C++94, Java adotou generics a partir de sua versão J2SE 5.0 (em 2004), C# a partir da versão 2.0, e agora é a vez do Object Pascal. (Apesar das diferenças de implementação e uso de generics em cada linguagem, o conceito é basicamente o mesmo.)
Pois bem. A comunidade do FPC terminou implementação de generics para sua versão 2.1.2 (em 2007) . Logo depois, a CodeGear anunciou sua intensão de incluir generics na próxima versão de seu compilador, porém com a sintaxe "ligeiramente" diferente.
Agora, com o lançamento do Delphi 2009, a CodeGear confirma a implementação da sintaxe antes exibida, para desespero da comunidade e, principalmente, dos usuários do FPC...
A sintaxe é "quase" a mesma. Mas como o "quase" faz não compilar, há muita gente de cabelo em pé.
The FPC Way...
- type
- generic MeuVetor< T > = class
- private
- _vetor: array of T;
- _limite: Integer;
- _atual: Integer;
- public
- constructor Create(tamanho: Integer);
- function Adicionar(item: T): Boolean;
- function Item(posicao: Integer): T;
- end;
- constructor MeuVetor.Create(tamanho: Integer);
- begin
- inherited Create();
- SetLength( _vetor, tamanho );
- _limite := tamanho;
- _atual := 0;
- end;
- function MeuVetor.Adicionar(item: T): Boolean;
- begin
- if ( _atual < _limite ) then
- begin
- _vetor[ _atual ] := item;
- Inc( _atual );
- Result := True;
- end
- else
- Result := False;
- end;
- function MeuVetor.Item(posicao: Integer): T;
- begin
- if ( ( posicao >= 0 ) and ( posicao < _limite ) ) then
- Result := _vetor[ posicao ]
- else
- raise Exception.Create( 'Posição fora da faixa.' );
- end;
The Delphi 2009 Way...
- type
- MeuVetor< T > = class
- private
- _vetor: array of T;
- _limite: Integer;
- _atual: Integer;
- public
- constructor Create(tamanho: Integer);
- function Adicionar(item: T): Boolean;
- function Item(posicao: Integer): T;
- end;
- constructor MeuVetor< T >.Create(tamanho: Integer);
- begin
- inherited Create();
- SetLength( _vetor, tamanho );
- _limite := tamanho;
- _atual := 0;
- end;
- function MeuVetor< T >.Adicionar(item: T): Boolean;
- begin
- if ( _atual < _limite ) then
- begin
- _vetor[ _atual ] := item;
- Inc( _atual );
- Result := True;
- end
- else
- Result := False;
- end;
- function MeuVetor< T >.Item(posicao: Integer): T;
- begin
- if ( ( posicao >= 0 ) and ( posicao < _limite ) ) then
- Result := _vetor[ posicao ]
- else
- raise Exception.Create( 'Posição fora da faixa.' );
- end;
Notou as diferenças ? Particularmente, eu prefiro sem a palavra generic na frente do nome da classe. Acho desnecessária. Como outras linguagens, também acho que deixar explícito na implementação dos métodos da classe a indicação de que ela recebe um parâmetro deixa o código mais fácil de entender. Na maneira implementada pelo FPC, se você não olhar a declaração, não vai saber que a classe é um generic. Não vai saber que "T" é um tipo que é parametrizado para a classe.
Em os futuros posts provavelmente darei exemplos de classes implementadas com generics em Object Pascal. Nessas usarei a sintaxe do Delphi 2009.
Espero que em breve possa haver um consenso. De imediato, seria bom se o FPC fizesse com que a palavra "generic" e a indicação dos tipos parametrizados na implementação dos métodos fossem opcionais. Poderia resolver temporariamente algum problema de portabilidade.