TCollection e Generics no Free Pascal - Uma breve visão sobre lista de objetos com o Lazarus

O Free Pascal pode não ser tão poderoso quanto o C++, mas em seus termos, está bem madura e tem evoluído - e para aplicações simples pode representar um excelente custo benefício, numa prova de que com ele é possível conciliar recursos poderosos com simplicidade.

[ Hits: 29.423 ]

Por: Perfil removido em 05/05/2010


Usando generics



O recurso de generics é recente até mesmo no Object Pascal do Delphi, surgiu no Delphi 2009 (meados de 2008). No Free Pascal está presente a partir da versão 2.3.1 (fim de 2007).

Aqui começaremos a ver como trabalhar com listas de objetos mesmo. Não temos mais uma classe de item (com suas propriedades) que é propriedade de uma coleção - temos nosso objeto autônomo e com sua identidade própria, podemos instanciá-lo e usá-lo individualmente ou então fazer uma lista com vários desses objetos. Outro grande lance é que essa lista não recebe um único tipo de objeto, ela pode armazenar qualquer tipo de objeto que descenda da classe desse objeto base (não iremos estender pra isso, mas é daí uma explicação pro termo "generics", podemos fazer listas de qualquer tipo de objeto, colocar nela não só objetos do tipo pré-definido na declaração mas também seus descendentes, enquanto na coleção só tínhamos lista de um único tipo de objeto, o TCollectionItem).

Então vamos começar pela classe dos objetos a serem listados. Como nosso exemplo é uma simples agenda, a classe é uma classe simples cujas propriedades são os campos de cada objeto que é um registro (uma pessoa na agenda). Também nem precisa implementar métodos pra essa classe, ela só tem mesmo propriedades declaradas.

{ TAgendaTelefonicaObj }
TAgendaTelefonicaObj = class
private
   FCodigo: Integer;
   FNome: String;
   FTelefone: String;
public
   property Codigo: Integer read FCodigo;
   property Nome: String read FNome write FNome;
   property Telefone: String read FTelefone write FTelefone;
end;

O próximo passo é criar a lista. Eu dei um nome a ela dentro do contexto e implementei um método e uma função semelhante ao que foi feito no exemplo da coleção pra manipular a inserção e a deleção de objetos da lista, mas no geral isso não seria necessário, mesmo assim, uma vez que a lista é genérica, se os métodos forem 'genéricos' essa mesma declaração de lista poderia ser aproveitada pra mais de um tipo de objetos além do esquema pai/descendentes, pois na verdade na declaração ela não sabe que tipo de objetos vai receber.

{ TAgendaTelefonicaGeneric }
generic TAgendaTelefonicaGeneric = class(TList)
public
   function Add(Item: T): Integer;
   procedure DeleteByCodigo(Codigo: Integer);
end;

Como dito acima, a exemplo da coleção, manipulamos a função Add pra gerar o nosso código interno do registro automaticamente e temos o método DeleteByCodigo que localiza o objeto pela respectiva propriedade e o deleta da lista. Note que como a lista é genérica na hora de manipular os itens dela (nossos objetos) precisamos fazer uso de typecast pra ter acesso às propriedades deles.

function TAgendaTelefonicaGeneric.Add(Item: T): Integer;var
  I: Integer;
begin
  //Pega a propriedade código do último objeto
  //e incrementa pra obter o código pro novo
  if Count = 0 then
    TAgendaTelefonicaObj(Item).FCodigo := 1
  else
  begin
    for I := 0 to Count - 1 do
      TAgendaTelefonicaObj(Item).FCodigo := TAgendaTelefonicaObj(Items[I]).Codigo + 1;
  end;

  //Insere
  Result := inherited Add(Item);
end;

procedure TAgendaTelefonicaGeneric.DeleteByCodigo(Codigo: Integer);
var
  I: Integer;
begin
  for I := 0 to Count - 1 do
    if TAgendaTelefonicaObj(Items[I]).Codigo = Codigo then
    begin
      Delete(I);
      Break;
    end;
end;

Para usarmos em nosso programa entra a última parte da declaração, que a classe que será instanciada e que no tipo especifica a nossa lista genérica. É uma única linha:

TAgendaTelefonicaListaGeneric = specialize TAgendaTelefonicaGeneric;

E daí lá no programa temos então temos como propriedade uma AgendaTelefonicaLista do tipo TAgendaTelefonicaListaGeneric que será de fato a lista usada. No método pra inserir declaramos uma var AgendaTelefonica do tipo TAgendaTelefonicaObj (lembra, o nosso objeto base). Não iremos mais passar valores pra um novo item como na coleção, iremos inserir na lista um objeto já existente.

AgendaTelefonica := TAgendaTelefonicaObj.Create();
AgendaTelefonica.Nome := LabeledEdit1.Text;
AgendaTelefonica.Telefone := LabeledEdit2.Text;
AgendaTelefonicaLista.Add(AgendaTelefonica);

Pra deletar a chamada do método customizado é igual ao da coleção.

AgendaTelefonicaLista.DeleteByCodigo(15);

E num exemplo de exibição da lista de objetos numa ListView semelhante ao que foi dito sobre a coleção temos:

for I := 0 to AgendaTelefonicaLista.Count - 1 do
begin
   Item := ListView1.Items.Add();
   Item.Caption := IntToStr(TAgendaTelefonicaObj(AgendaTelefonicaLista.Items[I]).Codigo);
   Item.SubItems.Add(TAgendaTelefonicaObj(AgendaTelefonicaLista.Items[I]).Nome);
   Item.SubItems.Add(TAgendaTelefonicaObj(AgendaTelefonicaLista.Items[I]).Telefone);
end;

Página anterior     Próxima página

Páginas do artigo
   1. Apresentação
   2. Coleções (TCollection)
   3. Usando generics
   4. Interface e código completo do exemplo
Outros artigos deste autor

Trabalhando com foto usando Cheese + GIMP + Xmorph

Lapidando a configuração do mplayer

Trabalhando com subredes

RAID 1 em Debian com sistema já instalado

Usando o SlackPorts

Leitura recomendada

Integrando saídas de comandos shell com sua aplicação Kylix

Capturando seu desktop com uma aplicação feita em kylix

Criando uma aplicação que mostra os processos em execução

Criando aplicação para detectar informações do sistema em Kylix

Colocando aplicação Kylix no TrayIcon do KDE

  
Comentários
[1] Comentário enviado por barao em 06/05/2010 - 11:23h

Bom artigo Pedro, tambem gosto muito da linguagem pascal e do c ,mais com as facilidades que o Lazaros vem incroporando a cada dia ele fica melhor.
Meu blog www.blig.ig.com.br/mauriciobaron

[2] Comentário enviado por andrezc em 07/05/2010 - 20:02h

Parabéns pelo artigo! Mas serei sincero com você, odeio Pascal, rs, isso é mais pq eu não gostei da sintaze, foi odio a primeira vista, em um curso que eu fiz.

Um abraço, parabéns pelo artigo.


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts