מטא־מתודת __newindex
חלק מהיחידה לוגיקה וזרימת התוכנית במסלול ה-Lua של Coddy. שיעור 19 מתוך 54.
למדת כיצד __index שולט במה שקורה כשמנסים לקרוא מפתח שאינו קיים בטבלה. עכשיו תגלה את המקבילה שלו: __newindex, ששולט במה שקורה כשמנסים להוסיף או לשנות זוג מפתח-ערך.
מתודת המטא __newindex מופעלת בכל פעם שמנסים להקצות ערך למפתח שאינו קיים כרגע בטבלה. כך אפשר ליירט שינויים ולשלוט בהם לפני שהם מתבצעים.
הנה דוגמה פשוטה שמונעת הוספה של מפתחות חדשים לטבלה:
local readOnly = {}
local meta = {
__newindex = function(table, key, value)
print("Cannot add key: " .. key)
end
}
setmetatable(readOnly, meta)
readOnly.name = "Alice" -- פלט: Cannot add key: name
print(readOnly.name) -- פלט: nilכשאתה מנסה להגדיר את readOnly.name = "Alice", Lua רואה שהמפתח name לא קיים בטבלה. במקום להוסיף אותו, Lua קוראת לפונקציה __newindex עם שלושה ארגומנטים: הטבלה עצמה, המפתח שמוגדר והערך שמוקצה.
בדוגמה הזאת, הפונקציה פשוט מדפיסה הודעה ולא באמת שומרת שום דבר.
אפשר גם להשתמש ב־__newindex כדי לאמת נתונים לפני שמאפשרים להכניס אותם לטבלה שלך:
local player = {}
local meta = {
__newindex = function(t, key, value)
if key == "health" and type(value) ~= "number" then
print("Health must be a number!")
else
rawset(t, key, value)
end
end
}
setmetatable(player, meta)
player.health = "high" -- פלט: Health must be a number!
player.health = 100 -- מותרשימו לב לשימוש ב־rawset() בדוגמה השנייה. הפונקציה הזו עוקפת את המטא־טבלה ומגדירה את הערך ישירות בטבלה.
בלעדיו, הגדרת הערך תפעיל שוב את __newindex, ותיצור לולאה אינסופית.
אתגר
קלכתוב פונקציה createValidatedTable שמקבלת key ו-value ומחזירה טבלה שמקבלת רק ערכי מחרוזת עבור מפתחות חדשים.
צור טבלה ריקה וצרף לה מטא-טבלה עם __newindex שבודקת את סוג הערך. אם מישהו מנסה להוסיף ערך שאינו מחרוזת, השתמש ב-rawset() כדי לאחסן במקומו את המחרוזת "invalid". עבור ערכי מחרוזת, אחסן אותם כרגיל באמצעות rawset().
לוגיקה:
- צור טבלה ריקה
- צור מטא-טבלה עם
__newindexשמקבלת את הטבלה, המפתח והערך - בתוך
__newindex, בדוק אם הערך הוא מחרוזת באמצעותtype(value) == "string" - אם זה מחרוזת, השתמש ב-
rawset(t, key, value)כדי לאחסן אותה - אם זו לא מחרוזת, השתמש ב-
rawset(t, key, "invalid")כדי לאחסן במקומה את"invalid" - צרף את המטא-טבלה לטבלה באמצעות
setmetatable() - השתמש ב-
rawset()כדי להוסיף לטבלה את צמד המפתח-ערך הראשוני (תוך עקיפת המטא-טבלה) - החזר את הטבלה
פרמטרים:
key(מחרוזת): המפתח הראשוני שיש להוסיף לטבלהvalue(מחרוזת): הערך הראשוני שיש להוסיף לטבלה
ערך מוחזר: טבלה עם אימות שמקבלת רק ערכי מחרוזת, ושמכילה את צמד המפתח-ערך הראשוני (טבלה)
נסו בעצמכם
function createValidatedTable(key, value)
-- כתבו כאן קוד
end
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה לוגיקה וזרימת התוכנית
1איטרציה מתקדמת בטבלאות
איטרציה באמצעות pairs()איטרציה באמצעות ipairs()pairs() לעומת ipairs()סיכום – גיליון דמות2פונקציות נוספות של ספריית הטבלאות
table.concat()בניית טבלה ו־unpack()table.sort()מיון מותאם אישית באמצעות פונקציותסיכום – לוח שיאיםתרגלו בעצמכם: קומפיילר Lua אונליין