Menu
Coddy logo textTech

Wzorzec iteratora

Część sekcji Programowanie obiektowe ścieżki Lua w Coddy. Lekcja 64 z 70.

Gdy masz kolekcję elementów przechowywaną w obiekcie, często chcesz przejść przez nią w pętli. Ogólna pętla for w Lua świetnie współpracuje z niestandardowymi iteratorami, a tę funkcjonalność możesz wbudować bezpośrednio w swoje klasy.

Wzorzec Iterator pozwala obiektowi kontrolować sposób przechodzenia przez jego wewnętrzne dane. Jedno eleganckie podejście wykorzystuje metametodę __call, która sprawia, że obiekt można wywołać jak funkcję. Każde wywołanie zwraca kolejny element, aż nie będzie już żadnych.

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

Po zdefiniowaniu __call możesz iterować za pomocą pętli while lub przekazać obiekt bezpośrednio do ogólnej pętli for:

local bag = Collection:new()
bag:add("apple")
bag:add("banana")

for item in bag do
    print(item)
end

Pętla wielokrotnie wywołuje bag(). Gdy __call zwraca nil (nie ma już więcej elementów), pętla się zatrzymuje. Ten wzorzec umieszcza logikę iteracji wewnątrz samego obiektu, dając Ci pełną kontrolę nad tym, jak i w jakiej kolejności uzyskuje się dostęp do elementów.

challenge icon

Wyzwanie

Łatwy

Zbudujmy klasę Playlist, po której można iterować za pomocą ogólnej pętli for w Lua! Zaimplementujesz wzorzec Iteratora przy użyciu metametody __call, dzięki czemu będzie można przechodzić przez playlistę utwór po utworze.

Podzielisz swój kod na dwa pliki:

  • Playlist.lua: Utwórz klasę Playlist, która przechowuje utwory. Twoja klasa potrzebuje konstruktora :new(), który inicjuje pustą listę utworów i ustawia indeks iteracji na 0. Dodaj metodę :addSong(title), aby dodawać utwory do playlisty. Co najważniejsze, zaimplementuj metametodę __call, tak aby za każdym razem, gdy playlista zostanie "called", zwracała następny utwór z listy (lub nil, gdy nie ma już kolejnych utworów).
  • main.lua: Załaduj moduł Playlist i utwórz nową playlistę. Dodaj do niej utwory na podstawie otrzymanych danych wejściowych, a następnie użyj ogólnej pętli for, aby przejść przez playlistę i wypisać tytuł każdego utworu w osobnym wierszu.

Magia wzorca Iteratora polega na tym, że obiekt Playlist staje się wywoływalny. Gdy użyjesz go w pętli for, Lua będzie wywoływać go wielokrotnie, aż zwróci nil, przekazując Ci kolejno każdy utwór.

Otrzymasz trzy dane wejściowe, z których każda reprezentuje tytuł utworu do dodania do playlisty (w podanej kolejności).

Na przykład, jeśli danymi wejściowymi są Bohemian Rhapsody, Stairway to Heaven i Hotel California, wynikiem powinno być:

Bohemian Rhapsody
Stairway to Heaven
Hotel California

Jeśli danymi wejściowymi są Yesterday, Imagine i Let It Be, wynikiem powinno być:

Yesterday
Imagine
Let It Be

Spróbuj swoich sił

-- Załaduj moduł Playlist
local Playlist = require('Playlist')

-- Wczytaj z wejścia trzy tytuły piosenek
local song1 = io.read()
local song2 = io.read()
local song3 = io.read()

-- TODO: Utwórz nową playlistę za pomocą Playlist:new()

-- TODO: Dodaj trzy piosenki do playlisty za pomocą :addSong()

-- TODO: Użyj ogólnej pętli for, aby przejść przez playlistę
-- i wypisz każdy tytuł piosenki w osobnym wierszu
-- Wskazówka: for song in playlist do ... end
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator Lua online