Pattern Iterator
Fa parte della sezione Programmazione orientata agli oggetti del percorso Lua di Coddy. Lezione 64 di 70.
Quando hai una raccolta di elementi memorizzati all’interno di un oggetto, spesso vuoi scorrerli con un ciclo. Il ciclo for generico di Lua funziona benissimo con iteratori personalizzati e puoi integrare questa funzionalità direttamente nelle tue classi.
Il pattern Iterator consente a un oggetto di controllare come vengono attraversati i suoi dati interni. Un approccio elegante utilizza il metametodo __call, che rende un oggetto richiamabile come una funzione. Ogni chiamata restituisce l'elemento successivo finché ce ne sono.
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
Con __call definito, puoi iterare usando un ciclo while oppure passare direttamente l'oggetto a un for generico:
local bag = Collection:new()
bag:add("apple")
bag:add("banana")
for item in bag do
print(item)
end
Il ciclo chiama bag() ripetutamente. Quando __call restituisce nil (nessun altro elemento), il ciclo si ferma. Questo schema racchiude la logica di iterazione all'interno dell'oggetto stesso, dandoti il pieno controllo su come e in quale ordine vengono recuperati gli elementi.
Sfida
FacileCreiamo una classe Playlist che puoi attraversare usando il ciclo generico for di Lua! Implementerai il pattern Iterator usando il metametodo __call, così da poter attraversare la playlist, una canzone alla volta.
Organizzerai il codice in due file:
Playlist.lua: crea una classe Playlist che memorizza internamente le canzoni. La classe deve avere un costruttore:new()che inizializza una lista di canzoni vuota e imposta l'indice di iterazione a 0. Aggiungi un metodo:addSong(title)per aggiungere canzoni alla playlist. Soprattutto, implementa il metametodo__callin modo che ogni volta che la playlist viene «chiamata», restituisca la canzone successiva della lista (oppurenilquando non ci sono più canzoni).main.lua: importa il modulo Playlist e crea una nuova playlist. Aggiungici le canzoni in base agli input che ricevi, poi usa un ciclo genericoforper attraversare la playlist e stampare il titolo di ogni canzone su una riga distinta.
La magia del pattern Iterator è che il tuo oggetto Playlist diventa richiamabile: quando viene usato in un ciclo for, Lua lo richiama ripetutamente finché non restituisce nil, fornendoti ogni canzone in sequenza.
Riceverai tre input, ognuno dei quali rappresenta il titolo di una canzone da aggiungere alla playlist (nell'ordine).
Per esempio, se gli input sono Bohemian Rhapsody, Stairway to Heaven e Hotel California, l'output dovrebbe essere:
Bohemian Rhapsody
Stairway to Heaven
Hotel CaliforniaSe gli input sono Yesterday, Imagine e Let It Be, l'output dovrebbe essere:
Yesterday
Imagine
Let It BeProvalo tu
-- Carica il modulo Playlist
local Playlist = require('Playlist')
-- Leggi tre titoli di canzoni dall'input
local song1 = io.read()
local song2 = io.read()
local song3 = io.read()
-- TODO: Crea una nuova playlist usando Playlist:new()
-- TODO: Aggiungi le tre canzoni alla playlist usando :addSong()
-- TODO: Usa un ciclo for generico per scorrere la playlist
-- e stampa il titolo di ogni canzone su una riga separata
-- Suggerimento: for song in playlist do ... end
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Il concetto di «self»
Tabelle con funzioni«self» esplicitoLa sintassi dei due puntiPunto o due puntiRiepilogo - Spostare il punto4Progetto: Banca digitale
Configurazione del progettoMetodo di deposito2Schema del prototipo di classe
Il concetto di prototipoCollegare con __indexIl costruttore :new()Inizializzare gli attributiIstanze indipendentiRiepilogo - Fabbrica di auto5Sovraccarico degli operatori nella OOP
Sommare oggettiSottrarre oggettiConcatenare oggettiConfrontare oggetti (<, >)Ripasso - Calcoli con il portafoglio8Incapsulamento
Convenzioni di denominazioneClosure per la privacyAccesso tramite closureTabelle di sola letturaLogica di convalidaRiepilogo - Cassaforte sicura11Modelli di progettazione (base)
Funzioni factoryTabella singletonPattern IteratorObserver (listener)Riepilogo - Factory per logger3Stato e comportamento degli oggetti
Variabili di istanzaMetodi getterMetodi setterProprietà calcolateFormattazione delle stringheControlli di uguaglianzaRiepilogo - Voto dello studente6Fondamenti dell'ereditarietà
Configurare l'ereditarietàEreditare i metodiEstendere il costruttoreAggiungere metodi alla classe figliaCondiviso vs specificoRiepilogo - Gerarchia delle formeEsercitati da solo: Compilatore Lua online