Menu
Coddy logo textTech

תבנית Iterator

חלק מהיחידה תכנות מונחה עצמים במסלול ה-Lua של Coddy. שיעור 64 מתוך 70.

כשיש לך אוסף של פריטים המאוחסנים בתוך אובייקט, לעיתים קרובות תרצה לעבור עליהם באמצעות לולאה. לולאת for הכללית של Lua עובדת היטב עם איטרטורים מותאמים אישית, ואפשר לשלב את הפונקציונליות הזו ישירות במחלקות שלך.

תבנית האיטרטור מאפשרת לאובייקט לשלוט באופן המעבר על הנתונים הפנימיים שלו. גישה אלגנטית אחת משתמשת במטא־מתודה __call, שהופכת אובייקט לניתן לקריאה כמו פונקציה. כל קריאה מחזירה את הפריט הבא עד שלא נותרו פריטים נוספים.

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

לאחר הגדרת __call, אפשר לבצע איטרציה באמצעות לולאת while או להעביר את האובייקט ישירות ללולאת for כללית:

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

for item in bag do
    print(item)
end

הלולאה קוראת שוב ושוב ל־bag(). כאשר __call מחזירה nil (אין עוד פריטים), הלולאה נעצרת. התבנית הזו מקפלת את לוגיקת האיטרציה בתוך האובייקט עצמו, וכך נותנת לך שליטה מלאה על האופן שבו הפריטים נגישים ועל סדר הגישה אליהם.

challenge icon

אתגר

קל

בואו נבנה מחלקת Playlist שאפשר לעבור עליה באמצעות לולאת for הגנרית של Lua! תיישמו את תבנית האיטרטור באמצעות המטא-מתודה __call, שתאפשר לעבור על רשימת ההשמעה שיר אחר שיר.

תארגנו את הקוד שלכם בשני קבצים:

  • Playlist.lua: צרו מחלקת Playlist ששומרת שירים באופן פנימי. המחלקה שלכם צריכה לכלול בנאי :new() שמאתחל רשימת שירים ריקה ומגדיר את אינדקס האיטרציה ל-0. הוסיפו מתודה :addSong(title) כדי להוסיף שירים לרשימת ההשמעה. והחשוב מכול, ממשו את המטא-מתודה __call כך שבכל פעם ש"רשימת ההשמעה נקראת", היא תחזיר את השיר הבא ברשימה (או nil כשלא נשארו שירים).
  • main.lua: השתמשו ב-require כדי לטעון את המודול Playlist שלכם וליצור רשימת השמעה חדשה. הוסיפו אליה שירים על סמך הקלטים שתקבלו, ואז השתמשו בלולאת for גנרית כדי לעבור על רשימת ההשמעה ולהדפיס כל כותרת שיר בשורה נפרדת.

הקסם של תבנית האיטרטור הוא שאובייקט Playlist שלכם הופך לניתן לקריאה; כשמשתמשים בו בלולאת for, ‏Lua קוראת לו שוב ושוב עד שהוא מחזיר nil, וכך מתקבל כל שיר לפי הסדר.

תקבלו שלושה קלטים, שכל אחד מהם מייצג כותרת של שיר להוספה לרשימת ההשמעה (לפי הסדר).

לדוגמה, אם הקלטים הם Bohemian Rhapsody, Stairway to Heaven ו-Hotel California, הפלט צריך להיות:

Bohemian Rhapsody
Stairway to Heaven
Hotel California

אם הקלטים הם Yesterday, Imagine ו-Let It Be, הפלט צריך להיות:

Yesterday
Imagine
Let It Be

נסו בעצמכם

-- טענו את המודול Playlist באמצעות require
local Playlist = require('Playlist')

-- קראו מהקלט שמות של שלושה שירים
local song1 = io.read()
local song2 = io.read()
local song3 = io.read()

-- TODO: צרו רשימת השמעה חדשה באמצעות Playlist:new()

-- TODO: הוסיפו את שלושת השירים לרשימת ההשמעה באמצעות :addSong()

-- TODO: השתמשו בלולאת for גנרית כדי לעבור על רשימת ההשמעה
-- והדפיסו את שמו של כל שיר בשורה נפרדת
-- רמז: for song in playlist do ... end
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר Lua אונליין