Menu
Coddy logo textTech

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.

challenge icon

Défi

Facile

Construisons 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 __call afin qu'à chaque fois que la playlist est « appelée », elle renvoie la chanson suivante de la liste (ou nil lorsqu'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érique for pour 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 California

Si les entrées sont Yesterday, Imagine et Let It Be, la sortie devrait être :

Yesterday
Imagine
Let It Be

Essayez 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
quiz iconTestez-vous

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

Entraînez-vous par vous-même : Compilateur Lua en ligne