Free Pascal - Usando TList

A classe TList é usada para gerenciar uma coleção de ponteiros, com a grande vantagem de ser dinâmica. Ela dispõe de métodos para fazer busca na lista e ordenar os elementos, entre outros. No exemplo abaixo fazemos uso de alguns desses métodos.


unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;

type
  TContato = class
    private
      NomeContato     : String;
      TelefoneContato : String;

    public
      property Nome : String
          read NomeContato;
      property Telefone : String
          read TelefoneContato;

      constructor Create(const pNomeContato       : String;
                         const pTelefoneContato   : String);
  end;

  { TfrmTlist }

  TfrmTlist = class(TForm)
    Button1: TButton;
    ListBox1: TListBox;
    procedure Button1Click(Sender: TObject);
  private
    { private declarations }
    Agenda : TList;

    procedure MostraAgenda;
  public
    { public declarations }
  end;

var
  frmTlist: TfrmTlist;

implementation

{$R *.lfm}

constructor TContato.Create(const pNomeContato      : String;
                             const pTelefoneContato : String);
begin
  self.NomeContato     := pNomeContato;
  self.TelefoneContato := pTelefoneContato;
end;

function comparaPorNome(Item1 : Pointer; Item2 : Pointer) : Integer;
var
  contato1, contato2 : TContato;
begin
  contato1 := TContato(Item1);
  contato2 := TContato(Item2);

  if      contato1.Nome > contato2.Nome
  then Result := 1
  else if contato1.Nome = contato2.Nome
  then Result := 0
  else Result := -1;
end;

procedure TfrmTlist.Button1Click(Sender: TObject);
var
  contato : TContato;

begin
  Agenda := TList.Create;

  contato := TContato.Create('Nádia Alves', '3523-0001');
  Agenda.Add(contato);
  contato := TContato.Create('Célio Silva', '3524-0000');
  Agenda.Add(contato);

  Agenda.Add(TContato.Create('Hélio Costa', '3320-1000'));
  Agenda.Add(TContato.Create('Aldo Sousa', '3321-0001'));

  MostraAgenda;
  ShowMessage('Ordenando pelo nome. Pressione OK');
  Agenda.Sort(@comparaPorNome);

  MostraAgenda;
  ShowMessage('Inserindo novo contato. Pressione OK');
  Agenda.Insert(2, TContato.Create('Luis Gonzaga', '3325-4000'));
  MostraAgenda;
  ShowMessage('Excluindo um contato. Pressione OK');
  Agenda.Delete(4);
  ShowMessage('Pressione OK');
  Agenda.free;
end;

procedure TfrmTlist.MostraAgenda;
var
  i : Integer;
begin
  ListBox1.Items.Clear;
  for i := 0 to Agenda.Count-1 do
  begin
    ListBox1.Items.Add(TContato(Agenda[i]).Nome+' - '+
                      (TContato(Agenda[i]).Telefone));
  end;
end;

end.


No exemplo criamos uma classe Contato que será usada para povoar um TList que denominamos Agenda. Um TListBox é usado para apresentar os dados do TList.
Nas linhas que vão de 74 a 95 é onde acontece tudo que pretendemos mostrar. Inicialmente o TList é criado. Em seguida, são criados vários objetos Contato, que são adicionados à Agenda utilizando o método Add(). Este método sempre adiciona um objeto no fim da lista.
Após isso chamamos o método MostraAgenda, que foi criado para visualizar os dados da Agenda no TListBox. Na linha 86 há uma chamada ao método Sort(), que recebe como argumento o método comparaPorNome(). Aqui cabe uma explicação mais detalhada.
A ordenação de uma lista de objetos não é uma coisa tão natural como ordenar números inteiros ou strings. Como sabemos um objeto tem vários campos e por isso precisamos definir qual o critério que será usado para decidir que um objeto A é maior, menor ou igual a um outro objeto B. Por este motivo o método Sort() deve receber como parâmetro uma variável procedural, ou seja, um método que estabelece o critério de ordenação.
Dessa forma, foi criado o método comparaPorNome(), que recebe os ponteiros dos dois objetos a serem comparados. Tal método deve retornar -1 se o primeiro objeto for menor que o segundo, 1 se for maior e 0 se forem iguais. No nosso exemplo definimos que dois Contatos são iguais quando tem nomes iguais. Leia mais sobre variáveis procedurais no post Free Pascal - Variáveis Procedurais. Deve-se ressaltar que o Free Pascal define apenas como deve ser a assinatura do método que ele espera receber em Sort(). A implementação cabe ao desenvolvedor.
Na linha 90 um novo objeto é inserido na posição 2 do TList. Note que a primeira posição é 0.
Usamos o método Delete() para deletar um objeto em uma determinada posição. Na linha 93 excluímos o objeto da posição 4.
Quando a TList não é mais necessária, liberamos a memória usada chamando Free. Para criar uma lista de strings prefira usar TStrings ou sua descendente TStringList.

8 comentários:

José Roberto disse...

ótimo conteúdo o seu blog prof. Carlos muito obrigada por dividir o seu conhecimento com todos nós, o seu blog já me ajudou muito em meus projetos só tenho a agradecer ao senhor !

Anônimo disse...

Estou usando o Lazarus -- eu Criei um pequeno programa, forneça dois valores e mostra a soma desses dois valores. Quando salvo o a minha aplicação como arquivo.exe ele não roda no windows 7. O que devo fazer? mauricio.s.trindade@hotmail.com - desde já agradeço!

Professor Carlos disse...

Você criou uma aplicação console ou com interface gráfica. Você salvou o projeto com a extensão .exe ou compilou o código? Não está muito claro pra mim o que você fez,

Adriane disse...

Olá professor Carlos ... seu blog está sendo muito útil para preparar minhas aulas para o curso de Análise de Desenvolvimento de Sistemas - Fatec/Mogi das Cruzes/SP. Obrigada por disponibilizar tanto conteúdo interessante para a aprendizagem ... Mudando de assunto estou querendo usar o Sender para verificar qual componente ativou determinado evento, mas o Lazarus não reconhece o 'sender' ???? aguardo ... e de qualquer forma obrigada ...

Professor Carlos disse...

Que bom que esta ajudando. Quanto ao Sender, tente referenciar o components assim, como neste exemplo: TButton(Sender)^.Caption

konlinuxguara disse...

Parabéns!

Sou usuário do GNU/Pascal, não conheço muito, porém a minha aprendizagem é crescente.
Sistema como calculadora, agenda, entre outros já consigo programar e usar, agora estou buscando um material que me auxilie a usar essa linguagem como se usa o PHP, em páginas para inserir dados e recuperá-los, pois usando o SGDB Postgresql faço todo desenvolvimento com PHP e HTML, e gostaria de implementar o conhecimento, como Gnu/Pascal.
Tudo faço no Slackware.
Grato.
http://konlinux.com

Anônimo disse...

Ex-aluna....:)
Professor Carlos estou querendo tirar uma dúvida, para instalar o firebird sendo que meu propósito é para o desenvolvimento de aplicações, como devo instalar? É como serviço ou aplicação? E

Professor Carlos disse...

Oi ex-aluna :)

De qualquer maneira uma aplicação se conectará ao banco de dados. Mas, se você instalar como aplicação cuide para que o servidor rode automaticamente na inicialização do sistema operacional. Isso dá pra configurar durante a instalação.

Django - Composição de queries brutas (raw queries)

Django Rest Framework (DRF) é uma poderosa ferramenta para criar Web APIs. Ele requer o uso de Python e do framework Django. Mesmo o Django...