Fala ai Radizeiro e Radizeira, tudo bem com você?
Vamos a mais um post dessa nossa série sobre generics, onde estamos esmiuçando todos os generics, tem sido bem legal.
Muitas vezes em nossas implementações rotineiras dentro do software, encontramos necessidades da utilização de listas, e muitos programadores desconhecem as listas genéricas ou usa de forma errada.
No nosso post de hoje estarei mostrando algumas das particularidades das listas genéricas e como utilizar corretamente.
Vamos lá?
Existem basicamente 4 tipo diferente de listas dentro do Delphi, nós temos o TList, TStack, TQueue e o TDictionary.
Esses são as 4 listas genéricas que iremos ver aqui dentro da nossa série sobre generics.
E hoje iremos ver o TList, o que é TList, e quais os recursos que tem dentro dele, e o que ele pode nos ajudar.
Já temos um exemplo aqui, não iremos montar do zero nesse momento, para poder mostrar melhor cada funcionalidade do TList.
Mas o que é o TList?
O TList é uma lista de coleções específicas, que você pode passar para o atributo genérico qualquer coisa, desde tipos primitivos como String, Integer, e até classes, como TForm, por exemplo.
Observe no código abaixo como é feita a implementação do TList.
private { Private declarations } ListaNum : TList<Integer>;
Nesse caso irei utilizar o tipo primitivo Integer, onde essa minha lista irá ter uma lista de inteiros.
Isso é legal para você validar os tipos de listas, onde você consegue fazer um constraint, como mostrado no post anterior, e fazer uma validação não deixando entrar qualquer tipo de objetos dentro dessa lista, você consegue validar o que essa lista irá receber, no nosso caso essa lista irá receber somente inteiros.
Toda as vezes que nós criamos uma lista, nós precisamos instanciar essa lista, para que ela funcione direitinho.
Como você viu no código anterior que eu criei uma variável dentro do private do meu formulário, com o nome de ListaNum, que será uma lista de números inteiros.
Como eu disse que devemos sempre instanciar a lista para que ela funcione direitinho?
Então, temos que ir no evento Create do formulário e instanciar essa nossa lista.
procedure TForm1.FormCreate(Sender: TObject); begin ListaNum := TList<Integer>.Create; end;
Observe que dentro do Create do formulário eu chamei a variável que está recebendo um TList de inteiros, e mandei criar, dessa forma já estamos com a nossa lista instanciada e a partir desse momento eu irei poder utilizá-la.
Então o que temos de recurso para essa nossa lista?
O primeiro recurso que temos aqui é para adicionar, onde digitamos um valor dentro do edit que encontra-se na tela do nosso formulário, e estarei adicionando um valor dentro da minha lista.
procedure TForm1.Button1Click(Sender: TObject); begin ListaNum.Add(StrToInt(Edit1.Text)); end;
Observe o código acima, chamei a variável de ListaNum, e quando chamamos as opções existentes dentro dessa nossa variável, é visto, como na imagem abaixo, que esse nosso Add está esperando um inteiro.
Mas por que eles está esperando um inteiro?
Porque, como disse logo no início, essa minha variável seria uma lista de inteiros.
Dentro do botão de Listar, foi implementando uma rotina para que possamos percorrer a lista e mostrar os itens adicionados a essa lista no Memo, como pode ser visto no código abaixo.
procedure TForm1.Button3Click(Sender: TObject); var I: Integer; begin Memo1.Lines.Clear; for I := 0 to Pred(ListaNum.Count) do Memo1.Lines.Add(ListaNum[I].ToString); end;
Observe o código acima que limpamos o Memo quando passamos a propriedade Clear, e dentro da estrutura de repetição for, ele percorre a lista, onde ele parte do 0 até a quantidade total de itens que tem na lista, e ela vai adicionando dentro do Memo o valor dessa lista.
Vamos ver isso funcionando?
Observe que adicionamos o 1, 2 e 3 na lista e logo depois listamos esses números adicionados na lista.
Nada de mais, e provavelmente você já usa muito isso, mas tem algumas coisas legais dentro da lista, e quero que você veja aqui no blog, pois talvez você não esteja utilizando isso, e pode ser uma mão na roda para você.
Para que possamos ter acesso aos itens da lista, nós acessamos através de um index, como você foi feito no código acima relacionado a listagem de itens da lista.
Em ListaNum[I], é passado dentro do colchetes uma variável do tipo inteiro, dessa forma estou acessando uma posição da lista, caso eu queira ir direto para uma posição específica, basta definir dentro dos colchetes o valor do index desejado.
Através de um index, eu posso acessar e também posso remover, vamos ver no código abaixo, que foi implementado dentro do botão de remover.
procedure TForm1.Button2Click(Sender: TObject); begin ListaNum.Delete(Pred(ListaNum.Count)); end;
Observe que para remover um tem da lista, basta chamar a lista passando o método Delete, e dentro desse método um index, sendo assim dentro desse código estou passando o Pred para retornar o último número dessa lista.
Então estou falando para lista, apaga por favor o último item da lista.
Então vamos adicionar novamente alguns itens a lista, listar e remover o último item.
Viu como é legal?
Simples e fácil de adicionar e remover itens dentro da lista, com essas duas funções eu tenho certeza que você já poderá utiliza em seu dia a dia.
Agora tem algumas coisinhas a mais que provavelmente você não utiliza, ou não tinha se atentado para esse poder dentro da lista genérica.
O primeiro deles que quero mostra para você é o comando chamado Capacity.
procedure TForm1.Button4Click(Sender: TObject); begin Memo1.Lines.Clear; Memo1.Lines.Add(ListaNum.Capacity.ToString); end;
Este comando irá nos ajudar a entender de como a lista funciona.
Creio eu que você já trabalhou com array, e já sabe como ele funciona, todas as vezes que você vai adicionar um novo campo no array, você tem que aumentar o tamanho desse array passando para o Setlength, se não você não irá conseguir adicionar novas informações.
A lista nada mais é que um array de informações, só que ela tem uma classe pode detrás fazendo o trabalho pesado para nós.
O Capacity, irá me retornar a capacidade da lista naquele momento, quantos registros minha lista pode ter naquele momento.
Ao clicar no botão que está com o código mostrado anteriormente, e retornado o valor zero.
Neste momento não foi adicionado nada na lista ainda, e é informado que eu não posso adicionar nada, mas se eu colocar o valor 1 no edit e mandar adicionar, ele irá aumentar a capacidade, observe.
Logo no início o Capacity me informou 0, e ao adicionar um item na lista, me retornou 4, ou seja, agora eu tenho capacidade para 4 itens.
Ele multiplica a capacidade de forma binária, onde ele reserva 4 posições na memória para essa lista, e ao passar de 4 ele adiciona mais 4, e por aí vai.
Você deve ficar atento a isso, porque eu tenho 4, mas adicionei 1, e se remover esse valor da lista, irei permanecer com as 4 posições na memória.
Se você alimentar uma lista, encher ela de itens, e depois limpar essa lista, o espaço na memória que ela já reservou para ser utilizada irá permanecer, a lista não é flexível, ela sempre irá manter esses espaços na memória.
Então tenha muita atenção quando for utilizar listas.
Talvez essa foi uma coisa que você nunca tenha percebido.
E agora temos um outro recurso bem simples que temos na lista, é o Count, que me retorna o total de registros dentro da lista.
procedure TForm1.Button5Click(Sender: TObject); begin Memo1.Lines.Clear; Memo1.Lines.Add(ListaNum.Count.ToString); end;
Esse código acima foi adicionado dentro do evento OnClique do botão com a descrição Count.
Na imagem abaixo você pode observar que minha capacidade é 4, e se eu chamar o Count ele me diz q só tenho 1.
Desta forma podemos observar que o Capacity, informa o tamanho que minha lista já reservou para trabalhar, e o count, o total de registros que tenho na lista.
Agora por último um recurso muito legal, o OnNotify.
Talvez você nunca tenha reparado esse recurso nas listas, mas a lista possui um evento, e você pode programar esse evento para coordenar as ações que acontecem dentro da lista.
Toda vez que acontecer alguma coisa dentro da lista você pode ser notificado em qualquer lugar do seu software através de um evento.
Veja como funciona.
procedure TForm1.Button6Click(Sender: TObject); begin ListaNum.OnNotify := Notificacao; end;
Esse OnNotify é um evento, que espera receber uma procedure que tem uma assinatura, que pode ser vista na imagem logo abaixo.
Nessa assinatura, ele espera um item do tipo inteiro.
Lembra que definimos o tipo genérico da nossa lista como um Inteiro?
Por este motivo a assinatura está aguardando um tipo inteiro, mas se não fosse, ele estaria esperando de outro tipo.
Neste caso se você criar uma procedure que tenha essa mesma assinatura.
Sendo assim foi criado um método sem retorno, ou seja, uma procedure chamada Notificacao.
private ... procedure Notificacao(Sender : TObject; const Item : Integer; Action : TCollectionNotification); ...
Por este motivo que o OnNotify mostrado no código anterior pode receber esse método Notifica, porque ele tem a mesma assinatura que ele está aguardando.
Agora todas as vezes que algum comportamento for alterado dentro da minha lista, essa minha procedure será acionada.
procedure TForm1.Notificacao(Sender: TObject; const Item: Integer; Action: TCollectionNotification); begin case Action of cnAdded: Memo1.Lines.Add('O Item ' + Item.ToString + ' foi adicionado'); cnRemoved: Memo1.Lines.Add('O Item ' + Item.ToString + ' foi removido'); end; end;
Esse método irá escrever no Memo os itens que foram inseridos ou removidos da lista.
Ao apertar o botão OnNotify eu informei que a partir desse momento ele irá passar a receber as notificações.
Agora tudo que for feito a partir desse momento será apresentado dentro do Memo, as notificações, de itens adicionados, ao removido.
Viu como é legal?
Você pode até criar um observer baseado só na lista.
Isso é muito legal, dá para você pensar um pouco mais na frente e eliminar um monte de código graças as listas genéricas, e a utilização do recurso OnNotify, aumenta mais ainda o leque de possibilidades que temos com a utilização de listas genéricas.
Show de bola né gente?
Espero que tenha sido bem legal, e de grande proveito os posts dessa nossa série de generics, estamos trabalhando com maior carinho para poder levar conteúdos que possam auxiliar em seu dia a dia.
E caso você tenha interesse de conhecer mais sobre generics acessa o nosso portal do CLUBE DE PROGRAMADORES EM DELPHI, onde você não só terá conteúdos relacionados aos generics, mas uma quantidade enorme de conteúdos que poderá lhe ajudar muito no seu dia a dia, é uma verdadeira NETFLIX para os programadores Delphi.
CLIQUE AQUI E SAIBA MAIS SOBRE O CLUBE DOS PROGRAMADORES DELPHI