Menu
CoddyTech

מיקסינים לעומת ירושה

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

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

השתמשו בירושה כאשר לאובייקטים יש זהות בסיסית משותפת. Bird הוא Animal. הגיוני ש-Bird יירש התנהגויות בסיסיות של בעלי חיים, כמו :eat() או :sleep(). הקשר הזה קבוע ומגדיר מהו האובייקט במהותו.

השתמשו במיקסינים כשאתם רוצים להוסיף יכולת שאינה מגדירה את זהות הליבה של האובייקט.

לא כל הציפורים יכולות לעוף: פינגווינים ויענים הם ציפורים, אבל הם לא עפים. תעופה היא יכולת, ולא תכונה שמגדירה ציפור. mixin בשם Flyable מאפשר להוסיף יכולת תעופה לציפורים שזקוקות לה, בלי לכפות אותה על כולן.

שתי הגישות פועלות יחד. כאן גם Eagle וגם Penguin יורשות מ־Bird, ורק Eagle מקבלת את המיקסין:

-- Bird יורשת מ-Animal (יחס של "הוא סוג של")
local Bird = {}
Bird.__index = Bird
setmetatable(Bird, {__index = Animal})

-- גם Eagle וגם Penguin הן ציפורים
local Eagle = setmetatable({}, {__index = Bird})
Eagle.__index = Eagle
local Penguin = setmetatable({}, {__index = Bird})
Penguin.__index = Penguin

-- Flyable היא יכולת (מיקסין)
local Flyable = {}
function Flyable:fly()
    print(self.name .. " soars through the sky!")
end

-- יש להחיל את המיקסין רק על הציפורים שעפות
applyMixin(Eagle, Flyable)

נשר יכול לקרוא ל־:fly(). פינגווין לא יכול: fly לא נמצא ב־Penguin, ב־Bird או ב־Animal, ולכן penguin:fly() הוא שגיאה. החלת המיקסין על Bird במקום זאת תעתיק את fly לכל ציפור, כולל פינגווינים.

challenge icon

אתגר

קל

בואו נבנה מערכת אקולוגית קטנה של יצורים שמדגימה מתי להשתמש בירושה לעומת במיקסינים! תיצרו מחלקת בסיס Animal, מחלקת Bird שיורשת ממנה, ומיקסין Swimmable, כי אף שכל הציפורים הן בעלי חיים, לא כל הציפורים יכולות לשחות.

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

  • Animal.lua: צרו את מחלקת הבסיס Animal עם בנאי :new(name) ששומר את השם. הוסיפו מתודת :eat() שמדפיסה {name} is eating. הדבר מייצג את הזהות הבסיסית המשותפת לכל בעלי החיים.
  • Swimmable.lua: צרו מיקסין עם מתודת :swim() שמדפיסה {self.name} is swimming. זוהי יכולת; לא כל היצורים יכולים לשחות, ולכן היא לא צריכה להיות חלק משרשרת הירושה.
  • Bird.lua: צרו מחלקת Bird שיורשת מ-Animal. הבנאי :new(name) צריך לקרוא לבנאי של מחלקת האב. הוסיפו מתודת :chirp() שמדפיסה {name} chirps!. זוהי התנהגות ייחודית לציפורים. אל תוסיפו שחייה למחלקת Bird: לא כל ציפור יכולה לשחות.
  • main.lua: כתבו כאן את פונקציית העזר applyMixin(target, mixin): היא מעתיקה כל פונקציה מהמיקסין אל היעד. קראו את שם הציפור והאם היא יכולה לשחות (yes או no). צרו מופע של Bird, ואם היא יכולה לשחות, החילו את המיקסין Swimmable על הציפור הזאת בלבד. לאחר מכן קראו ל-:eat() (שירושה מ-Animal) ול-:chirp() (המתודה של Bird עצמה), וקראו ל-:swim() רק אם המתודה קיימת אצל הציפור הזאת (if bird.swim then).

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

  1. שם הציפור (מחרוזת)
  2. האם הציפור יכולה לשחות: yes או no

אם הציפור יכולה לשחות, הפלט שלכם צריך להיות:

{name} is eating
{name} chirps!
{name} is swimming

אם הציפור לא יכולה לשחות, הפלט שלכם צריך להיות:

{name} is eating
{name} chirps!

לדוגמה, אם הקלט הוא Duck ו-yes, הפלט צריך להיות:

Duck is eating
Duck chirps!
Duck is swimming

אם הקלט הוא Sparrow ו-no, הפלט צריך להיות:

Sparrow is eating
Sparrow chirps!

האתגר הזה מדגים את ההבחנה המרכזית: Bird היא Animal (ירושה), אבל שחייה היא יכולת אופציונלית (מיקסין). מכיוון שהמיקסין מתווסף רק לציפורים שיכולות לשחות, לציפור שלא יכולה לשחות אין כלל מתודת swim.

נסו בעצמכם

-- main.lua: נקודת כניסה - יצירת ציפור והדגמת היכולות שלה

-- פונקציית עזר להחלת mixin על מחלקה או על אובייקט יחיד
local function applyMixin(target, mixin)
    -- TODO: להעתיק כל פונקציה מ-mixin אל target

end

local Bird = require('Bird')
local Swimmable = require('Swimmable')

-- קריאת הקלטים
local name = io.read()
local canSwimInput = io.read()

-- TODO: ליצור מופע של Bird עם השם

-- TODO: אם הקלט הוא "yes", להחיל את ה-mixin של Swimmable על הציפור הזו בלבד

-- TODO: לקרוא ל-eat() - עברה בירושה מ-Animal

-- TODO: לקרוא ל-chirp() - המתודה של Bird עצמו

-- TODO: לקרוא ל-swim() רק אם לציפור הזו יש אותה
quiz iconבחנו את עצמכם

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

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

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