Iterator-Muster
Teil des Abschnitts Objektorientierte Programmierung der Lua-Journey von Coddy. Lektion 64 von 70.
Wenn du eine Sammlung von Elementen hast, die in einem Objekt gespeichert sind, möchtest du oft durch sie hindurch iterieren. Die generische for-Schleife von Lua funktioniert hervorragend mit benutzerdefinierten Iteratoren, und du kannst diese Funktionalität direkt in deine Klassen integrieren.
Das Iterator-Muster ermöglicht es einem Objekt, zu steuern, wie seine internen Daten durchlaufen werden. Ein eleganter Ansatz verwendet die __call-Metamethode, durch die ein Objekt wie eine Funktion aufgerufen werden kann. Jeder Aufruf gibt das nächste Element zurück, bis keine weiteren mehr vorhanden sind.
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
Mit __call definiert kannst du mit einer while-Schleife iterieren oder das Objekt direkt an eine generische for-Schleife übergeben:
local bag = Collection:new()
bag:add("apple")
bag:add("banana")
for item in bag do
print(item)
end
Die Schleife ruft bag() wiederholt auf. Wenn __call nil zurückgibt (keine weiteren Elemente), wird die Schleife beendet. Dieses Muster kapselt die Iterationslogik im Objekt selbst und gibt dir die vollständige Kontrolle darüber, wie und in welcher Reihenfolge auf die Elemente zugegriffen wird.
Aufgabe
EinfachErstellen wir eine Playlist-Klasse, durch die du mithilfe von Lua's generischer for-Schleife iterieren kannst! Du implementierst das Iterator-Muster mithilfe der __call-Metamethode, sodass deine Playlist Song für Song durchlaufen werden kann.
Du organisierst deinen Code auf zwei Dateien:
Playlist.lua: Erstelle eine Playlist-Klasse, die Songs intern speichert. Deine Klasse benötigt einen:new()-Konstruktor, der eine leere Songliste initialisiert und den Iterationsindex auf 0 setzt. Füge eine:addSong(title)-Methode hinzu, um Songs zur Playlist hinzuzufügen. Am wichtigsten ist, die__call-Metamethode zu implementieren, sodass die Playlist bei jedem „Aufruf“ den nächsten Song aus der Liste zurückgibt (odernil, wenn keine weiteren Songs vorhanden sind).main.lua: Binde dein Playlist-Modul ein und erstelle eine neue Playlist. Füge ihr basierend auf den Eingaben, die du erhältst, Songs hinzu. Verwende anschließend eine generischefor-Schleife, um durch die Playlist zu iterieren und jeden Songtitel in einer eigenen Zeile auszugeben.
Der Zauber des Iterator-Musters besteht darin, dass dein Playlist-Objekt aufrufbar wird. Wenn es in einer for-Schleife verwendet wird, ruft Lua es wiederholt auf, bis es nil zurückgibt, sodass du jeden Song der Reihe nach erhältst.
Du erhältst drei Eingaben, die jeweils einen Songtitel darstellen, der deiner Playlist hinzugefügt werden soll (in dieser Reihenfolge).
Wenn die Eingaben beispielsweise Bohemian Rhapsody, Stairway to Heaven und Hotel California lauten, sollte die Ausgabe wie folgt aussehen:
Bohemian Rhapsody
Stairway to Heaven
Hotel CaliforniaWenn die Eingaben Yesterday, Imagine und Let It Be lauten, sollte die Ausgabe wie folgt aussehen:
Yesterday
Imagine
Let It BeProbier es selbst
-- Lade das Playlist-Modul
local Playlist = require('Playlist')
-- Lies drei Songtitel von der Eingabe
local song1 = io.read()
local song2 = io.read()
local song3 = io.read()
-- TODO: Erstelle eine neue Playlist mit Playlist:new()
-- TODO: Füge die drei Songs mit :addSong() zur Playlist hinzu
-- TODO: Verwende eine generische for-Schleife, um durch die Playlist zu iterieren
-- und gib jeden Songtitel in einer eigenen Zeile aus
-- Hinweis: for song in playlist do ... end
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Das 'self'-Konzept
Tabellen mit FunktionenExplizites 'self'Die Doppelpunkt-SyntaxPunkt vs. DoppelpunktZusammenfassung – Beweglicher Punkt4Projekt: Digitale Bank
Projekt-SetupEinzahlungsmethode7Polymorphie & Überschreiben
Methoden überschreibenElternmethoden aufrufenDuck TypingGemeinsames InterfaceTyp prüfenRückblick - Mitarbeiterrollen10Projekt: Formen-Manager
Projekt-SetupRechteck-KlasseKreis-KlasseUmfang-MethodeFormen-SammlungGesamtflächeFormen filtern2Klassen-Prototyp-Muster
Das Prototyp-KonzeptVerknüpfung mit __indexDer :new()-KonstruktorAttribute initialisierenUnabhängige InstanzenZusammenfassung – Autofabrik5Operatorüberladung in OOP
Objekte addierenObjekte subtrahierenObjekte verkettenObjekte vergleichen (<, >)Rückblick – Wallet-Mathematik8Kapselung
NamenskonventionenClosures für private DatenZugriff über ClosuresSchreibgeschützte TabellenValidierungslogikZusammenfassung – Sicherer Tresor11Entwurfsmuster (Lite)
Factory-FunktionenSingleton-TabelleIterator-MusterObserver (Listener)Wiederholung – Logger-Factory3Objektzustand und -verhalten
InstanzvariablenGetter-MethodenSetter-MethodenBerechnete EigenschaftenStrings formatierenGleichheitsprüfungenZusammenfassung – Studentennote6Grundlagen der Vererbung
Das Vererbungs-SetupMethoden vererbenDen Konstruktor erweiternChild-Methoden hinzufügenGemeinsam vs. EinzigartigZusammenfassung - Formen-Hierarchie9Komposition & Mixins
Has-A-BeziehungDelegationEinfache MixinsAnwendung mehrerer MixinsMixins vs. VererbungZusammenfassung – Roboter-Montage12Abschluss-Herausforderungen
Wiederholung - InventarsystemWiederholung - BenutzerverwaltungWiederholung - Score-TrackerFinaler OOP-CheckÜbe selbstständig: Online-Lua-Compiler