Menu
Coddy logo textTech

מטא־מתודת __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, ותיצור לולאה אינסופית.

challenge icon

אתגר

קל
כתוב פונקציה 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
quiz iconבחנו את עצמכם

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

כל השיעורים ביחידה לוגיקה וזרימת התוכנית

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