Menu
Coddy logo textTech

טבלאות לקריאה בלבד

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

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

מתודת המטא __newindex מיירטת ניסיונות להקצות ערכים חדשים לטבלה. על ידי כך שתגרום לה לחסום את כל ההקצאות, תוכל להקפיא אובייקט:

local ImmutablePoint = {}

function ImmutablePoint.new(x, y)
    local data = {x = x, y = y}
    
    local proxy = {}
    setmetatable(proxy, {
        __index = data,
        __newindex = function()
            error("Cannot modify immutable object")
        end
    })
    
    return proxy
end

הטריק הוא להשתמש בטבלת פרוקסי. הנתונים בפועל נמצאים ב־data, בעוד שהמשתמש עובד עם proxy הריק.

בעת קריאה, __index שולף מתוך data. בעת כתיבה, __newindex מופעל במקום זאת, ואנחנו חוסמים אותו:

local p = ImmutablePoint.new(10, 20)
print(p.x)  -- 10 (הקריאה עובדת)
p.x = 50    -- שגיאה: אי אפשר לשנות אובייקט בלתי ניתן לשינוי

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

challenge icon

אתגר

קל

בואו נבנה מחלקת ImmutableConfig שיוצרת אובייקטי תצורה לקריאה בלבד! לאחר יצירתם, אובייקטי התצורה האלה צריכים לאפשר לקרוא את ההגדרות שלהם, אך לחסום לחלוטין כל ניסיון לשנות אותן.

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

  • ImmutableConfig.lua: צרו מודול שמייצר אובייקטי תצורה קפואים. הפונקציה .new(appName, version, maxUsers) שלכם צריכה לאחסן את שלושת הערכים האלה באופן פנימי, ואז להחזיר טבלת proxy שמאפשרת לקרוא את כל השדות אך מונעת כל שינוי. כשמנסים לשנות ערך, יש להדפיס Error: Config is read-only במקום להעלות שגיאה ממשית.
  • main.lua: הפעילו את ImmutableConfig שלכם! קראו שלוש קלטים עבור ערכי התצורה, צרו אובייקט תצורה, ואז הדגימו שהוא פועל כראוי על ידי:
    • הדפסת שלושת הערכים המקוריים
    • ניסיון לשנות את השדה maxUsers (שאמור להפעיל את הודעת השגיאה)
    • הדפסת maxUsers שוב כדי להוכיח שהוא לא השתנה בפועל

תקבלו שלוש קלטים:

  1. שם היישום (מחרוזת)
  2. הגרסה (מחרוזת)
  3. מספר המשתמשים המרבי (מספר)

הפלט שלכם צריך להציג את ערכי התצורה, את השגיאה בעת ניסיון לשנות אותם, ואישור שהערך נותר ללא שינוי:

App: {appName}
Version: {version}
Max Users: {maxUsers}
Error: Config is read-only
Max Users: {maxUsers}

לדוגמה, אם הקלטים הם MyApp, 2.0 ו-100, הפלט צריך להיות:

App: MyApp
Version: 2.0
Max Users: 100
Error: Config is read-only
Max Users: 100

זכרו: תבנית ה-proxy משתמשת בטבלה ריקה שהמשתמש עובד איתה, בעוד שהנתונים בפועל נמצאים בטבלה פנימית נפרדת. מטודת המטא __index שולפת נתונים מטבלת הנתונים, ו-__newindex לוכדת (וחוסמת) כל ניסיון כתיבה!

נסו בעצמכם

-- ייבא את המודול ImmutableConfig
local ImmutableConfig = require('ImmutableConfig')

-- קרא את הקלטים
local appName = io.read()
local version = io.read()
local maxUsers = tonumber(io.read())

-- TODO: צור אובייקט הגדרות באמצעות ImmutableConfig.new()

-- TODO: הדפס את כל שלושת הערכים המקוריים בפורמט הבא:
-- App: {appName}
-- Version: {version}
-- Max Users: {maxUsers}

-- TODO: נסה לשנות את השדה maxUsers (פעולה זו אמורה להציג הודעת שגיאה)

-- TODO: הדפס שוב את maxUsers כדי להוכיח שהוא לא השתנה
quiz iconבחנו את עצמכם

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

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

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