טיפוסיות ברווז
חלק מהיחידה תכנות מונחה עצמים במסלול ה-Lua של Coddy. שיעור 39 מתוך 70.
Lua לא מתעניינת במחלקה של אובייקט. אכפת לה רק ממה שהאובייקט יכול לעשות. המושג הזה נקרא טיפוס ברווז: "אם הוא הולך כמו ברווז ומגעגע כמו ברווז, הוא ברווז." במונחי תכנות, אם יש לאובייקט המתודה שאת קוראת לה, היא עובדת.
המשמעות היא שאפשר להשתמש יחד במחלקות שאינן קשורות כלל, כל עוד יש להן שם מתודה משותף:
local Circle = {}
Circle.__index = Circle
function Circle:new()
local obj = {}
setmetatable(obj, Circle)
return obj
end
function Circle:draw()
print("Drawing a circle")
end
local Square = {}
Square.__index = Square
function Square:new()
local obj = {}
setmetatable(obj, Square)
return obj
end
function Square:draw()
print("Drawing a square")
endלמחלקות האלה אין קשר של ירושה: הן עצמאיות לחלוטין. ובכל זאת, אפשר להתייחס אליהן באופן זהה:
local shapes = {Circle:new(), Square:new(), Circle:new()}
for _, shape in ipairs(shapes) do
shape:draw()
end
-- פלט:
-- מציירים עיגול
-- מציירים ריבוע
-- מציירים עיגולהלולאה לא בודקת מהו הטיפוס של כל אובייקט. היא פשוט קוראת ל־:draw() וסומכת על כך שהמתודה קיימת. הגמישות הזאת עוצמתית. אפשר להוסיף סוגים חדשים של צורות בלי לשנות כלל את קוד הלולאה. כל עוד המחלקה החדשה מממשת את :draw(), זה פשוט עובד.
אתגר
קלנדגים את העוצמה של טיפוס ברווז על ידי בניית מערכת התראות עם מחלקות שאין ביניהן שום קשר, וכולן יכולות להיות מעובדות באותה דרך!
תיצרו שלוש מחלקות התראות עצמאיות, שאף אחת מהן לא יורשת מהאחרות, אבל כולן מממשות מתודה :send(). המשמעות היא שתוכלו לעבור בלולאה על אוסף מעורב ולקרוא ל־:send() בכל אחת מהן בלי להתחשב בסוג שלה בפועל.
תארגנו את הקוד שלכם בארבעה קבצים:
Email.lua: מחלקה עם בנאי:new(recipient)ששומרת למי נשלח האימייל. המתודה:send()שלה צריכה להדפיסEmailing {recipient}.SMS.lua: מחלקה נפרדת לחלוטין עם בנאי:new(phoneNumber). המתודה:send()שלה צריכה להדפיסTexting {phoneNumber}.PushNotification.lua: מחלקה עצמאית נוספת עם בנאי:new(deviceId). המתודה:send()שלה צריכה להדפיסPushing to {deviceId}.main.lua: חברו את הכול יחד! קראו שלושה קלטים, צרו מופע אחד מכל סוג של התראה, הכניסו את כולם לטבלה אחת, ואז עברו עליהם בלולאה וקראו ל־:send()בכל אחד מהם.
תקבלו שלושה קלטים:
- נמען של אימייל (למשל,
alice@example.com) - מספר טלפון (למשל,
555-1234) - מזהה מכשיר (למשל,
device_99)
בקובץ הראשי שלכם, צרו את כל שלושת אובייקטי ההתראה, שמרו אותם בטבלה ועברו על הטבלה תוך קריאה ל־:send() בכל אחד מהם. הסדר צריך להיות: תחילה Email, אחר כך SMS, ואז PushNotification.
לדוגמה, אם הקלטים הם bob@mail.com, 555-9876 ו־phone_42, הפלט צריך להיות:
Emailing bob@mail.com
Texting 555-9876
Pushing to phone_42שימו לב שהלולאה שלכם לא צריכה לבדוק מהו הסוג של כל אובייקט. היא פשוט סומכת על כך שלכל אובייקט באוסף יש מתודה :send(). זאת דוגמה לטיפוס ברווז בפעולה! אם הוא יכול לבצע :send(), הוא התראה.
נסו בעצמכם
-- main.lua
-- רכזו את כל סוגי ההתראות והדגימו טיפוס ברווזי
-- ייבאו את המחלקות של ההתראות
local Email = require('Email')
local SMS = require('SMS')
local PushNotification = require('PushNotification')
-- קראו את הקלטים
local recipient = io.read()
local phoneNumber = io.read()
local deviceId = io.read()
-- TODO: צרו מופע אחד מכל סוג התראה
-- TODO: הכניסו את כל ההתראות לטבלה אחת (קודם Email, אחר כך SMS, ואז PushNotification)
-- TODO: עברו על הטבלה בלולאה וקראו ל־:send() עבור כל התראה
-- כך מדגימים טיפוס ברווזי – לא בודקים את הסוג, אלא פשוט קוראים ל־:send()
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
4פרויקט: בנק דיגיטלי
הגדרת הפרויקטפעולת הפקדה7פולימורפיזם ודריסת מתודות
דריסת מתודותקריאה למתודות של מחלקת האבטיפוסיות ברווזממשק משותףבדיקת טיפוססיכום – תפקידי עובדים2תבנית אב־טיפוס למחלקה
מושג אב־הטיפוסקישור באמצעות __indexהבנאי :new()אתחול מאפייניםמופעים עצמאייםסיכום – מפעל מכוניות5העמסת אופרטורים בתכנות מונחה עצמים
חיבור אובייקטיםחיסור אובייקטיםשרשור אובייקטיםהשוואת אובייקטים (<, >)חזרה – חישובים עם ארנק8כימוס
כללי מתן שמותClosures לשמירה על פרטיותגישה באמצעות Closuresטבלאות לקריאה בלבדלוגיקת אימותסיכום – כספת מאובטחת11תבניות עיצוב (בקצרה)
פונקציות Factoryטבלת Singletonתבנית IteratorObserver (מאזין)סיכום – מפעל Logger3מצב והתנהגות של אובייקטים
משתני מופעמתודות Getterמתודות Setterמאפיינים מחושביםעיצוב מחרוזותבדיקות שוויוןסיכום – ציון תלמיד6יסודות הירושה
הכנת מבנה הירושהירושת מתודותהרחבת הבנאיהוספת מתודות למחלקת הבתמשותף לעומת ייחודיסיכום – היררכיית צורותתרגלו בעצמכם: קומפיילר Lua אונליין