Menu
Coddy logo textTech

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.

challenge icon

Sfida

Facile

Creiamo 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 __call in modo che ogni volta che la playlist viene «chiamata», restituisca la canzone successiva della lista (oppure nil quando 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 generico for per 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 California

Se gli input sono Yesterday, Imagine e Let It Be, l'output dovrebbe essere:

Yesterday
Imagine
Let It Be

Provalo 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
quiz iconMettiti alla prova

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

Esercitati da solo: Compilatore Lua online