הרחבת הבנאי
חלק מהיחידה תכנות מונחה עצמים במסלול ה-Lua של Coddy. שיעור 33 מתוך 70.
כשמחלקת בת יורשת ממחלקת אב, לעיתים קרובות תרצה שבנאי של מחלקת הבת יאתחל את כל מה שבנאי של מחלקת האב היה מאתחל, וגם שדות נוספים הייחודיים למחלקת הבת. במקום לשכפל קוד, אפשר לקרוא ישירות לבנאי של מחלקת האב.
הטכניקה כוללת שימוש בשם מחלקת האב כדי להפעיל את המתודה :new() שלה, תוך העברת self כארגומנט הראשון. כך נוצר אובייקט הבסיס עם כל האתחול של מחלקת האב, שאותו ניתן להתאים למחלקת הילד.
local Vehicle = {}
Vehicle.__index = Vehicle
function Vehicle:new(speed)
local obj = {speed = speed}
setmetatable(obj, Vehicle)
return obj
end
-- Car יורשת מ-Vehicle
local Car = {}
Car.__index = Car
setmetatable(Car, {__index = Vehicle})
function Car:new(speed, brand)
local obj = Vehicle.new(Vehicle, speed) -- קראו לבנאי של מחלקת האב
obj.brand = brand -- הוסיפו שדה ייחודי למחלקת הבת
setmetatable(obj, Car) -- קשרו מחדש ל-Car
return obj
endשימו לב לשלבים העיקריים בבנאי של המחלקה הצאצאית: ראשית, אנו קוראים ל־Vehicle.new(Vehicle, speed) כדי לקבל אובייקט שהשדה speed כבר מוגדר בו. לאחר מכן נוסיף את השדה brand הייחודי למחלקה הצאצאית. לבסוף, נשנה את המטא־טבלה מ־Vehicle ל־Car כדי שהמופע יחפש מתודות במחלקה הצאצאית תחילה.
אפשר גם להשתמש בתחביר נקודתיים בעת קריאה לבנאי של מחלקת האב: Vehicle:new(speed) שקול ל־Vehicle.new(Vehicle, speed), מכיוון ששניהם מעבירים את Vehicle כארגומנט הראשון. שתי הצורות פועלות כאן כראוי, לכן אפשר להשתמש בזו שנראית לך קריאה יותר.
local myCar = Car:new(120, "Toyota")
print(myCar.speed) -- פלט: 120
print(myCar.brand) -- פלט: Toyotaהתבנית הזו שומרת על הקוד שלך DRY: לוגיקת אתחול משותפת נמצאת במחלקת האב, בעוד שכל מחלקת צאצא מטפלת רק במאפיינים הייחודיים שלה.
אתגר
קלבואו נבנה היררכיית יצורים שבה מחלקת בן יורשת את הבנאי של מחלקת האב שלה! תיצרו מחלקת אב Animal ומחלקת בן Bird, שבה הבנאי של Bird קורא לבנאי של Animal כדי לטפל באתחול המשותף לפני הוספת מאפיין ייחודי משלו.
תארגנו את הקוד בשלושה קבצים:
Animal.lua: הגדירו את מחלקת האב שלכם עם בנאי:new(name)ששומר את שם החיה. כללו מתודה:describe()שמדפיסה את שם החיה. הגדירו את תבנית המחלקה המקובלת באמצעות__indexוהחזירו את המחלקה.Bird.lua: הגדירו את מחלקת הבן שיורשת מ־Animal. הבנאי:new(name, wingspan)של Bird צריך לקרוא לבנאי האב באמצעותAnimal.new(Animal, name)כדי לאתחל את השם, ואז להוסיף את השדהwingspanלאובייקט, ולבסוף לקשר מחדש את המטא־טבלה ל־Bird. כללו מתודה:info()שמדפיסה גם את השם וגם את מוטת הכנפיים בפורמט מסוים.main.lua: ייבאו את המודול Bird, קראו שני קלטים (שם ומוטת כנפיים), צרו מופע של Bird וקראו לשתי המתודות כדי להדגים שהפונקציונליות שעוברת בירושה והפונקציונליות הייחודית למחלקת הבן פועלות יחד.
תקבלו שני קלטים:
- שם הציפור
- מוטת הכנפיים של הציפור (מספר)
בקובץ הראשי שלכם, צרו Bird עם השם ומוטת הכנפיים הנתונים. לאחר מכן קראו ל־:describe() ואחריו ל־:info() בשורות נפרדות.
המתודה :describe() (שעוברת בירושה מ־Animal) צריכה להדפיס:
Animal: {name}המתודה :info() (המוגדרת ב־Bird) צריכה להדפיס:
{name} has a wingspan of {wingspan}לדוגמה, אם הקלטים הם Eagle ו־200, הפלט צריך להיות:
Animal: Eagle
Eagle has a wingspan of 200הנקודה החשובה היא שהבנאי של Bird לא משכפל את אתחול השם. הוא מעביר את המשימה הזאת לבנאי של Animal, ואז מוסיף רק את מה שייחודי לציפורים. כך הקוד שלכם נשאר DRY, ובמקביל נבנית שרשרת ירושה תקינה!
נסו בעצמכם
-- main.lua: נקודת הכניסה
local Bird = require('Bird')
-- קריאת הקלטים
local name = io.read()
local wingspan = tonumber(io.read())
-- TODO: צרו מופע של Bird עם השם ומוטת הכנפיים הנתונים
-- TODO: קראו ל־:describe() על הציפור (מתודה שירשה מ־Animal)
-- TODO: קראו ל־:info() על הציפור (מתודה שמוגדרת ב־Bird)
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
4פרויקט: בנק דיגיטלי
הגדרת הפרויקטפעולת הפקדה7פולימורפיזם ודריסת מתודות
דריסת מתודותקריאה למתודות של מחלקת האבטיפוסיות ברווזממשק משותףבדיקת טיפוססיכום – תפקידי עובדים2תבנית אב־טיפוס למחלקה
מושג אב־הטיפוסקישור באמצעות __indexהבנאי :new()אתחול מאפייניםמופעים עצמאייםסיכום – מפעל מכוניות5העמסת אופרטורים בתכנות מונחה עצמים
חיבור אובייקטיםחיסור אובייקטיםשרשור אובייקטיםהשוואת אובייקטים (<, >)חזרה – חישובים עם ארנק8כימוס
כללי מתן שמותClosures לשמירה על פרטיותגישה באמצעות Closuresטבלאות לקריאה בלבדלוגיקת אימותסיכום – כספת מאובטחת11תבניות עיצוב (בקצרה)
פונקציות Factoryטבלת Singletonתבנית IteratorObserver (מאזין)סיכום – מפעל Logger3מצב והתנהגות של אובייקטים
משתני מופעמתודות Getterמתודות Setterמאפיינים מחושביםעיצוב מחרוזותבדיקות שוויוןסיכום – ציון תלמיד6יסודות הירושה
הכנת מבנה הירושהירושת מתודותהרחבת הבנאיהוספת מתודות למחלקת הבתמשותף לעומת ייחודיסיכום – היררכיית צורותתרגלו בעצמכם: קומפיילר Lua אונליין