Patron Iterator
Fait partie de la section Object Oriented Programming du Journey Lua de Coddy — leçon 64 sur 70.
Lorsque vous avez une collection d'éléments stockés à l'intérieur d'un objet, vous voulez souvent les parcourir en boucle. La boucle for générique de Lua fonctionne à merveille avec des itérateurs personnalisés, et vous pouvez intégrer cette fonctionnalité directement dans vos classes.
Le patron Iterator permet à un objet de contrôler la manière dont ses données internes sont parcourues. Une approche élégante utilise la métaméthode __call, qui rend un objet appelable comme une fonction. Chaque appel retourne l'élément suivant jusqu'à ce qu'il n'y en ait plus.
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
Avec __call défini, vous pouvez itérer en utilisant une boucle while ou passer l'objet directement à un for générique :
local bag = Collection:new()
bag:add("apple")
bag:add("banana")
for item in bag do
print(item)
end
La boucle appelle bag() de manière répétée. Lorsque __call retourne nil (plus d'éléments), la boucle s'arrête. Ce modèle encapsule la logique d'itération à l'intérieur de l'objet lui-même, vous donnant un contrôle total sur la manière — et l'ordre — dont les éléments sont accédés.
Défi
FacileConstruisons une classe Playlist que vous pouvez parcourir à l'aide de la boucle for générique de Lua ! Vous allez implémenter le modèle Iterator en utilisant la métaméthode __call, permettant à votre playlist d'être parcourue chanson par chanson.
Vous organiserez votre code sur deux fichiers :
Playlist.lua: Créez une classe Playlist qui stocke les chansons en interne. Votre classe a besoin d'un constructeur:new()qui initialise une liste de chansons vide et définit l'index d'itération à 0. Ajoutez une méthode:addSong(title)pour ajouter des chansons à la playlist. Plus important encore, implémentez la métaméthode__callde sorte que chaque fois que la playlist est « appelée », elle renvoie la chanson suivante de la liste (ounillorsqu'il n'y a plus de chansons).main.lua: Importez votre module Playlist et créez une nouvelle playlist. Ajoutez-y des chansons en fonction des entrées que vous recevez, puis utilisez une boucleforgénérique pour parcourir la playlist et afficher chaque titre de chanson sur sa propre ligne.
La magie du modèle Iterator est que votre objet Playlist devient appelable — lorsqu'il est utilisé dans une boucle for, Lua l'appelle de manière répétée jusqu'à ce qu'il renvoie nil, vous donnant chaque chanson en séquence.
Vous recevrez trois entrées, chacune représentant un titre de chanson à ajouter à votre playlist (dans l'ordre).
Par exemple, si les entrées sont Bohemian Rhapsody, Stairway to Heaven, et Hotel California, la sortie devrait être :
Bohemian Rhapsody
Stairway to Heaven
Hotel CaliforniaSi les entrées sont Yesterday, Imagine, et Let It Be, la sortie devrait être :
Yesterday
Imagine
Let It BeAide-mémoire
Le pattern Iterator permet à un objet de contrôler la manière dont ses données internes sont parcourues en implémentant une logique d'itération personnalisée.
Utilisez la métaméthode __call pour rendre un objet appelable comme une fonction. Chaque appel renvoie l'élément suivant jusqu'à ce qu'il n'y en ait plus (renvoie nil) :
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
Avec __call défini, vous pouvez utiliser l'objet directement dans une boucle for générique :
local bag = Collection:new()
bag:add("apple")
bag:add("banana")
for item in bag do
print(item)
end
La boucle appelle l'objet de manière répétée. Lorsque __call renvoie nil, la boucle s'arrête automatiquement.
Essayez vous-même
-- Requiert le module Playlist
local Playlist = require('Playlist')
-- Lit trois titres de chansons à partir de l'entrée
local song1 = io.read()
local song2 = io.read()
local song3 = io.read()
-- TODO: Créer une nouvelle playlist en utilisant Playlist:new()
-- TODO: Ajouter les trois chansons à la playlist en utilisant :addSong()
-- TODO: Utiliser une boucle for générique pour parcourir la playlist
-- et afficher chaque titre de chanson sur sa propre ligne
-- Indice : for song in playlist do ... end
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Object Oriented Programming
1Le concept de « self »
Tables avec fonctions« self » expliciteLa syntaxe avec deux-pointsPoint vs deux-pointsRécapitulatif - Point mobile4Projet : Banque numérique
Configuration du projetMéthode de dépôt7Polymorphisme et Redéfinition
Redéfinition de méthodesAppeler des méthodes parentesDuck TypingInterface communeVérification du typeRécapitulatif - Rôles des employés10Projet : Gestionnaire de formes
Configuration du projetClasse Rectangle2Modèle de prototype de classe
Le concept de prototypeLiaison avec __indexLe constructeur :new()Initialisation des attributsInstances indépendantesRécapitulatif - Usine de voitures5Surcharge d'opérateurs en POO
Additionner des objetsSoustraire des objetsConcaténer des objetsComparer des objets (<, >)Récapitulatif - Calculs de portefeuille8Encapsulation
Conventions de nommageClosures pour la confidentialitéAccès via les ClosuresTables en lecture seuleLogique de validationRécapitulatif - Coffre-fort sécurisé11Patrons de conception (Lite)
Fonctions FactoryTable SingletonPatron IteratorObserver (Écouteur)Récapitulatif - Logger Factory3État et comportement des objets
Variables d'instanceMéthodes GetterMéthodes SetterPropriétés calculéesFormatage de chaînesVérifications d'égalitéRécapitulatif - Note de l'étudiant6Bases de l'héritage
Mise en place de l'héritageHériter des méthodesÉtendre le constructeurAjouter des méthodes enfantsPartagé vs UniqueRécapitulatif - Hiérarchie des formes