תבנית 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 (אין עוד פריטים), הלולאה נעצרת. התבנית הזו מקפלת את לוגיקת האיטרציה בתוך האובייקט עצמו, וכך נותנת לך שליטה מלאה על האופן שבו הפריטים נגישים ועל סדר הגישה אליהם.
אתגר
קלבואו נבנה מחלקת 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
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
4פרויקט: בנק דיגיטלי
הגדרת הפרויקטפעולת הפקדה7פולימורפיזם ודריסת מתודות
דריסת מתודותקריאה למתודות של מחלקת האבטיפוסיות ברווזממשק משותףבדיקת טיפוססיכום – תפקידי עובדים2תבנית אב־טיפוס למחלקה
מושג אב־הטיפוסקישור באמצעות __indexהבנאי :new()אתחול מאפייניםמופעים עצמאייםסיכום – מפעל מכוניות5העמסת אופרטורים בתכנות מונחה עצמים
חיבור אובייקטיםחיסור אובייקטיםשרשור אובייקטיםהשוואת אובייקטים (<, >)חזרה – חישובים עם ארנק8כימוס
כללי מתן שמותClosures לשמירה על פרטיותגישה באמצעות Closuresטבלאות לקריאה בלבדלוגיקת אימותסיכום – כספת מאובטחת11תבניות עיצוב (בקצרה)
פונקציות Factoryטבלת Singletonתבנית IteratorObserver (מאזין)סיכום – מפעל Logger3מצב והתנהגות של אובייקטים
משתני מופעמתודות Getterמתודות Setterמאפיינים מחושביםעיצוב מחרוזותבדיקות שוויוןסיכום – ציון תלמיד6יסודות הירושה
הכנת מבנה הירושהירושת מתודותהרחבת הבנאיהוספת מתודות למחלקת הבתמשותף לעומת ייחודיסיכום – היררכיית צורותתרגלו בעצמכם: קומפיילר Lua אונליין