Padrão Iterator
Parte da seção Programação Orientada a Objetos do Journey de Lua da Coddy. Lição 64 de 70.
Quando você tem uma coleção de itens armazenada dentro de um objeto, geralmente quer percorrê-la em um loop. O loop genérico for do Lua funciona muito bem com iteradores personalizados, e você pode incorporar essa funcionalidade diretamente às suas classes.
O padrão Iterator permite que um objeto controle como seus dados internos são percorridos. Uma abordagem elegante usa o metamétodo __call, que torna um objeto chamável como uma função. Cada chamada retorna o próximo item até que não haja mais nenhum.
local Collection = {}
Collection.__index = Collection
function Collection:new()
local obj = { items = {}, index = 0 }
setmetatable(obj, Collection)
return obj
end
function Collection:add(item)
table.insert(self.items, item)
end
function Collection:__call()
self.index = self.index + 1
return self.items[self.index]
end
Com __call definido, você pode iterar usando um while loop ou passar o objeto diretamente para um for genérico:
local bag = Collection:new()
bag:add("apple")
bag:add("banana")
for item in bag do
print(item)
end
O loop chama bag() repetidamente. Quando __call retorna nil (não há mais itens), o loop para. Esse padrão encapsula a lógica de iteração dentro do próprio objeto, dando a você controle total sobre como e em que ordem os itens são acessados.
Desafio
FácilVamos criar uma classe Playlist que você poderá percorrer usando o for genérico do Lua! Você implementará o padrão Iterator usando o metamétodo __call, permitindo que sua playlist seja percorrida música por música.
Você organizará seu código em dois arquivos:
Playlist.lua: crie uma classe Playlist que armazene as músicas internamente. Sua classe precisa de um construtor:new()que inicialize uma lista de músicas vazia e defina o índice de iteração como 0. Adicione um método:addSong(title)para adicionar músicas à playlist. Mais importante, implemente o metamétodo__callpara que, cada vez que a playlist for "chamada", ela retorne a próxima música da lista (ounilquando não houver mais músicas).main.lua: importe seu módulo Playlist e crie uma nova playlist. Adicione músicas a ela com base nas entradas recebidas e, em seguida, use um loopforgenérico para percorrer a playlist e imprimir o título de cada música em sua própria linha.
A magia do padrão Iterator é que seu objeto Playlist se torna chamável; quando usado em um loop for, o Lua o chama repetidamente até que ele retorne nil, fornecendo cada música em sequência.
Você receberá três entradas, cada uma representando o título de uma música a ser adicionada à sua playlist (nessa ordem).
Por exemplo, se as entradas forem Bohemian Rhapsody, Stairway to Heaven e Hotel California, a saída deverá ser:
Bohemian Rhapsody
Stairway to Heaven
Hotel CaliforniaSe as entradas forem Yesterday, Imagine e Let It Be, a saída deverá ser:
Yesterday
Imagine
Let It BeExperimente você mesmo
-- Requer o módulo Playlist
local Playlist = require('Playlist')
-- Lê três títulos de músicas da entrada
local song1 = io.read()
local song2 = io.read()
local song3 = io.read()
-- TODO: Crie uma nova playlist usando Playlist:new()
-- TODO: Adicione as três músicas à playlist usando :addSong()
-- TODO: Use um laço for genérico para iterar pela playlist
-- e imprima cada título de música em sua própria linha
-- Dica: for song in playlist do ... end
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1O Conceito 'Self'
Tabelas com Funções'self' ExplícitoA Sintaxe de Dois-pontosPonto vs Dois-pontosRecapitulação - Movendo o Ponto4Projeto: Banco Digital
Configuração do ProjetoMétodo de Depósito7Polimorfismo e Sobrescrita
Sobrescrita de MétodosChamando Métodos da Classe PaiDuck TypingInterface ComumVerificando o TipoRecapitulação - Papéis de Funcionários10Projeto: Gerenciador de Formas
Configuração do ProjetoClasse RetânguloClasse CírculoMétodo PerímetroColeção de FormasÁrea TotalFiltrar Formas2Padrão de Protótipo de Classe
O Conceito de ProtótipoVinculando com __indexO Construtor :new()Inicializando AtributosInstâncias IndependentesRecapitulação - Fábrica de Carros5Sobrecarga de Operadores em POO
Somando ObjetosSubtraindo ObjetosConcatenando ObjetosComparando Objetos (<, >)Recapitulação - Matemática de Carteira8Encapsulamento
Convenções de NomenclaturaClosures para PrivacidadeAcesso via ClosuresTabelas Somente LeituraLógica de ValidaçãoRecapitulação - Cofre Seguro11Padrões de Projeto (Lite)
Funções FactoryTabela SingletonPadrão IteratorObserver (Listener)Recapitulação - Logger Factory3Estado e Comportamento do Objeto
Variáveis de InstânciaMétodos GetterMétodos SetterPropriedades CalculadasFormatação de StringsVerificações de IgualdadeRecapitulação - Nota do Aluno6Fundamentos de Herança
Configurando a HerançaHerdando MétodosEstendendo o ConstrutorAdicionando Métodos FilhosCompartilhado vs ÚnicoRecapitulação - Hierarquia de FormasPratique por conta própria: Compilador de Lua online