Patron Iterator
Fait partie de la section Programmation orientée objet du Journey Lua de Coddy. Leçon 64 sur 70.
Lorsque vous avez une collection d’éléments stockée dans un objet, vous souhaitez souvent les parcourir. La boucle générique for de Lua fonctionne parfaitement avec des itérateurs personnalisés, et vous pouvez intégrer directement cette fonctionnalité à 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 permet d’appeler un objet comme une fonction. Chaque appel renvoie 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 effectuer une itération à l’aide d’une boucle while ou transmettre directement l’objet à 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 renvoie nil (plus aucun élément), la boucle s’arrête. Ce modèle encapsule la logique d’itération dans l’objet lui-même, ce qui vous donne un contrôle total sur la manière et l’ordre d’accès aux éléments.
Défi
FacileConstruisons une classe Playlist que vous pourrez parcourir à l'aide de la boucle générique for de Lua ! Vous implémenterez le patron Iterator à l'aide de la métaméthode __call, ce qui permettra de parcourir votre playlist chanson par chanson.
Vous organiserez votre code dans deux fichiers :
Playlist.lua: créez une classe Playlist qui stocke les chansons en interne. Votre classe doit disposer 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__callafin qu'à 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: exigez votre module Playlist et créez une nouvelle playlist. Ajoutez-y les chansons correspondant aux entrées reçues, puis utilisez une boucle génériqueforpour parcourir la playlist et afficher le titre de chaque chanson sur sa propre ligne.
La magie du patron Iterator est que votre objet Playlist devient appelable : lorsqu'il est utilisé dans une boucle for, Lua l'appelle à plusieurs reprises jusqu'à ce qu'il renvoie nil, ce qui vous fournit chaque chanson dans l'ordre.
Vous recevrez trois entrées, chacune représentant le titre d'une 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 BeEssayez vous-même
-- Requiert le module Playlist
local Playlist = require('Playlist')
-- Lire trois titres de chansons depuis 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 Programmation orientée objet
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 RectangleClasse CercleMéthode PérimètreCollection de formesAire totaleFiltrer les formes2Modè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 formesEntraînez-vous par vous-même : Compilateur Lua en ligne