Patrón Iterador
Parte de la sección Programación Orientada a Objetos del Journey de Lua de Coddy. Lección 64 de 70.
Cuando tienes una colección de elementos almacenada dentro de un objeto, a menudo quieres recorrerlos. El for genérico de Lua funciona perfectamente con iteradores personalizados, y puedes incorporar esta funcionalidad directamente en tus clases.
El patrón Iterator permite que un objeto controle cómo se recorren sus datos internos. Un enfoque elegante utiliza el método metamágico __call, que hace que un objeto se pueda invocar como una función. Cada llamada devuelve el siguiente elemento hasta que no quedan más.
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 definido, puedes iterar usando un bucle while o pasar el objeto directamente a un for genérico:
local bag = Collection:new()
bag:add("apple")
bag:add("banana")
for item in bag do
print(item)
end
El bucle llama a bag() repetidamente. Cuando __call devuelve nil (no quedan más elementos), el bucle se detiene. Este patrón encapsula la lógica de iteración dentro del propio objeto, lo que te da un control total sobre cómo y en qué orden se accede a los elementos.
Desafío
Fácil¡Construyamos una clase Playlist que puedas recorrer mediante el bucle genérico for de Lua! Implementarás el patrón Iterador usando el metamétodo __call, lo que permitirá recorrer tu lista de reproducción canción por canción.
Organizarás tu código en dos archivos:
Playlist.lua: Crea una clase Playlist que almacene las canciones internamente. Tu clase necesita un constructor:new()que inicialice una lista de canciones vacía y establezca el índice de iteración en 0. Añade un método:addSong(title)para agregar canciones a la lista de reproducción. Lo más importante es implementar el metamétodo__callpara que cada vez que se "llame" a la lista de reproducción, devuelva la siguiente canción de la lista (onilcuando no haya más canciones).main.lua: Requiere tu módulo Playlist y crea una nueva lista de reproducción. Añádele canciones según las entradas que recibas; después, usa un bucle genéricoforpara recorrer la lista de reproducción e imprimir el título de cada canción en su propia línea.
La magia del patrón Iterador consiste en que tu objeto Playlist se vuelve invocable: cuando se usa en un bucle for, Lua lo llama repetidamente hasta que devuelve nil, proporcionándote cada canción en secuencia.
Recibirás tres entradas, cada una representando el título de una canción que se añadirá a tu lista de reproducción (en orden).
Por ejemplo, si las entradas son Bohemian Rhapsody, Stairway to Heaven y Hotel California, la salida debería ser:
Bohemian Rhapsody
Stairway to Heaven
Hotel CaliforniaSi las entradas son Yesterday, Imagine y Let It Be, la salida debería ser:
Yesterday
Imagine
Let It BePruébalo tú mismo
-- Requiere el módulo Playlist
local Playlist = require('Playlist')
-- Lee tres títulos de canciones de la entrada
local song1 = io.read()
local song2 = io.read()
local song3 = io.read()
-- TODO: Crea una nueva playlist usando Playlist:new()
-- TODO: Añade las tres canciones a la playlist usando :addSong()
-- TODO: Usa un bucle for genérico para iterar a través de la playlist
-- e imprime cada título de canción en su propia línea
-- Hint: for song in playlist do ... end
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1El concepto de 'self'
Tablas con funciones'self' explícitoLa sintaxis de dos puntosPunto vs. dos puntosResumen - Punto en movimiento4Proyecto: Banco Digital
Configuración del proyectoMétodo de depósito2Patrón de prototipo de clase
El concepto de prototipoVinculación con __indexEl constructor :new()Inicialización de atributosInstancias independientesResumen - Fábrica de coches5Sobrecarga de operadores en POO
Sumar objetosRestar objetosConcatenar objetosComparar objetos (<, >)Resumen - Matemáticas de la billetera8Encapsulamiento
Convenciones de nomenclaturaClosures para privacidadAcceso mediante ClosuresTablas de solo lecturaLógica de validaciónResumen - Bóveda segura11Patrones de diseño (Lite)
Funciones FactoryTabla SingletonPatrón IteradorObserver (Listener)Resumen - Logger Factory3Estado y Comportamiento de los Objetos
Variables de InstanciaMétodos GetterMétodos SetterPropiedades CalculadasFormateo de StringsComprobaciones de IgualdadResumen - Calificación del Estudiante6Fundamentos de la herencia
Configuración de la herenciaHerencia de métodosExtender el constructorAñadir métodos hijosCompartido vs. ÚnicoResumen: Jerarquía de formasPractica por tu cuenta: Compilador de Lua online