מאפיינים מחושבים
חלק מהיחידה תכנות מונחה עצמים במסלול ה-Lua של Coddy. שיעור 15 מתוך 70.
פונקציות גישה (getters) ופונקציות עדכון (setters) מאפשרות גישה לערכים שמורים, אבל לפעמים דרושים לך נתונים שאינם קיימים כשדה שמור. צריך לחשב אותם מתוך מאפיינים אחרים. אלה נקראים מאפיינים מחושבים.
חשבו על מלבן. אתם שומרים את הרוחב והגובה שלו, אבל השטח לא נשמר בשום מקום: הוא מחושב על ידי הכפלת שני הערכים האלה זה בזה. במקום לשמור נתונים מיותרים, אתם יוצרים מתודה שמחשבת ומחזירה את התוצאה:
local Rectangle = {}
Rectangle.__index = Rectangle
function Rectangle:new(width, height)
local instance = {}
setmetatable(instance, self)
instance.width = width
instance.height = height
return instance
end
function Rectangle:getArea()
return self.width * self.height
endהמתודה :getArea() לא מחזירה ערך שמור. היא מחשבת את השטח מחדש בכל פעם שקוראים לה. לגישה הזאת יש יתרון מרכזי: אם הרוחב או הגובה משתנים, השטח משקף אוטומטית את המידות החדשות, בלי שתצטרכו לעדכן דבר.
local box = Rectangle:new(5, 3)
print(box:getArea()) -- פלט: 15
box.width = 10
print(box:getArea()) -- פלט: 30מאפיינים מחושבים שומרים על עקביות האובייקטים שלך. במקום לאחסן ערכים שתלויים בשדות אחרים (ולהסתכן בכך שהם יתיישנו), מחשבים אותם לפי הצורך. התבנית הזו מתאימה לכל נתון נגזר: היקפים, ממוצעים, מחרוזות בפורמט מסוים או כל ערך שאפשר לקבוע על סמך מאפיינים קיימים.
אתגר
קלבואו נבנה מחלקת Box שמחשבת את הנפח שלה לפי דרישה! במקום לאחסן את הנפח כשדה, תיצרו מאפיין מחושב שמחשב אותו ממידות התיבה בכל פעם שהוא נדרש.
תארגנו את הקוד שלכם בשני קבצים:
Box.lua: הגדירו את מחלקתBoxבאמצעות תבנית האב־טיפוס המקובלת. כל תיבה שומרת שלוש מידות:width,height, ו-depth. כללו:- בנאי
:new(width, height, depth)ששומר את שלוש המידות - מתודה
:getVolume()שמחשבת ומחזירה את הנפח (width × height × depth) - מתודה
:getSurfaceArea()שמחשבת ומחזירה את שטח הפנים הכולל
- בנאי
main.lua: טענו את מודול Box, צרו מופע של תיבה והדגימו כיצד המאפיינים המחושבים משקפים אוטומטית את המידות הנוכחיות.
שטח הפנים של תיבה מחושב כך: 2 × (width×height + height×depth + width×depth)
תקבלו שלוש קלטים שמייצגים את מידות התיבה:
- רוחב
- גובה
- עומק
בקובץ הראשי, צרו תיבה עם המידות הנתונות, ואז הדפיסו שתי שורות:
- הנפח באמצעות
:getVolume() - שטח הפנים באמצעות
:getSurfaceArea()
לדוגמה, אם הקלטים הם 3, 4, ו-5, הפלט צריך להיות:
60
94היתרון במאפיינים מחושבים הוא שהם תמיד נשארים מדויקים. אם תשנו בהמשך אחת ממידות התיבה, קריאה חוזרת ל-:getVolume() תחזיר אוטומטית את הערך החדש והנכון: אין צורך בעדכונים ידניים!
נסו בעצמכם
-- טען את המודול Box באמצעות require
local Box = require('Box')
-- קרא את הממדים מהקלט
local width = tonumber(io.read())
local height = tonumber(io.read())
local depth = tonumber(io.read())
-- TODO: צור מופע של Box עם הממדים הנתונים
-- TODO: הדפס את הנפח באמצעות :getVolume()
-- TODO: הדפס את שטח הפנים באמצעות :getSurfaceArea()
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
4פרויקט: בנק דיגיטלי
הגדרת הפרויקטפעולת הפקדה7פולימורפיזם ודריסת מתודות
דריסת מתודותקריאה למתודות של מחלקת האבטיפוסיות ברווזממשק משותףבדיקת טיפוססיכום – תפקידי עובדים2תבנית אב־טיפוס למחלקה
מושג אב־הטיפוסקישור באמצעות __indexהבנאי :new()אתחול מאפייניםמופעים עצמאייםסיכום – מפעל מכוניות5העמסת אופרטורים בתכנות מונחה עצמים
חיבור אובייקטיםחיסור אובייקטיםשרשור אובייקטיםהשוואת אובייקטים (<, >)חזרה – חישובים עם ארנק8כימוס
כללי מתן שמותClosures לשמירה על פרטיותגישה באמצעות Closuresטבלאות לקריאה בלבדלוגיקת אימותסיכום – כספת מאובטחת11תבניות עיצוב (בקצרה)
פונקציות Factoryטבלת Singletonתבנית IteratorObserver (מאזין)סיכום – מפעל Logger3מצב והתנהגות של אובייקטים
משתני מופעמתודות Getterמתודות Setterמאפיינים מחושביםעיצוב מחרוזותבדיקות שוויוןסיכום – ציון תלמיד6יסודות הירושה
הכנת מבנה הירושהירושת מתודותהרחבת הבנאיהוספת מתודות למחלקת הבתמשותף לעומת ייחודיסיכום – היררכיית צורותתרגלו בעצמכם: קומפיילר Lua אונליין