Menu
Coddy logo textTech

למה ב-Go אין ירושה

חלק מהיחידה תכנות מונחה עצמים במסלול ה-GO של Coddy. שיעור 34 מתוך 107.

שפות מסורתיות מונחות עצמים כמו Java ו-C++ משתמשות בירושה כדי לשתף קוד בין טיפוסים. מחלקת בת מרחיבה מחלקת אב ויורשת את כל השדות והמתודות שלה. Go משמיטה תכונה זו במכוון.

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

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

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

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

  • ממשקים מגדירים חוזי התנהגות ללא פרטי מימוש
  • הטמעת מבנים מאפשרת לטיפוסים לכלול טיפוסים אחרים ולעשות שימוש חוזר במתודות שלהם

חשבו על ההשוואה הזאת. ב-OOP מסורתי, ייתכן שתכתבו class Dog extends Animal. ב-Go, משלבים מבנה Animal בתוך Dog ומממשים ממשקים משותפים. התוצאה היא פונקציונליות דומה עם צימוד רופף יותר בין טיפוסים.

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

challenge icon

אתגר

קל

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

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

  • notifier.go: הגדירו ממשק Notifier עם מתודה אחת, Notify(message string) string. צרו גם מבנה BaseNotifier עם שדה Name, שיוטמע בטיפוסים אחרים. הוסיפו ל-BaseNotifier מתודה בשם Format(message string) string, שמחזירה את ההודעה כששם מודיע ההתראות מופיע לפניה בסוגריים מרובעים.
  • channels.go: צרו שני טיפוסים של ערוצי התראות שמטמיעים את BaseNotifier ומממשים את הממשק Notifier:
    • EmailNotifier עם שדה נוסף בשם Address
    • SMSNotifier עם שדה נוסף בשם Phone
    המתודה Notify של כל טיפוס צריכה להשתמש במתודת Format המוטמעת ולכלול בפלט את המידע הספציפי לערוץ שלו.
  • main.go: צרו פונקציה בשם SendAlert שמקבלת כל Notifier והודעה, ואז מחזירה את התוצאה של הקריאה ל-Notify. קראו את פרטי ההתראות מהקלט, צרו את שני טיפוסי מודיעי ההתראות והדגימו כיצד אפשר להשתמש בהם לסירוגין באמצעות הממשק.

הקלט שיסופק יהיה בפורמט הבא:

  • שורה 1: שם מודיע ההתראות עבור אימייל
  • שורה 2: כתובת אימייל
  • שורה 3: שם מודיע ההתראות עבור SMS
  • שורה 4: מספר טלפון
  • שורה 5: הודעת התראה

מתודת Format שלכם ב-BaseNotifier צריכה להחזיר:

[Name] message

מתודות Notify שלכם צריכות להחזיר:

  • EmailNotifier: Email to [Address]: [formatted message]
  • SMSNotifier: SMS to [Phone]: [formatted message]

לדוגמה, בהינתן Alerts, user@mail.com, Urgent, 555-1234 ו-Server down, הפלט שלכם צריך להיות:

Email to user@mail.com: [Alerts] Server down
SMS to 555-1234: [Urgent] Server down

שימו לב ששני טיפוסי מודיעי ההתראות משתמשים מחדש במתודת Format מתוך BaseNotifier באמצעות הטמעה, בעוד שכל אחד מהם מספק מימוש משלו של Notify. הפונקציה SendAlert עובדת עם כל Notifier בלי לדעת מהו הטיפוס הקונקרטי. כך נראית הרכבה במקום ירושה בפעולה.

נסו בעצמכם

package main

import (
	"bufio"
	"fmt"
	"os"
)

// SendAlert מקבלת כל Notifier והודעה, ומחזירה את תוצאת הקריאה ל-Notify
// TODO: ממשו את הפונקציה SendAlert

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	
	// קראו את שם שולח ההתראות בדוא"ל
	scanner.Scan()
	emailName := scanner.Text()
	
	// קראו את כתובת הדוא"ל
	scanner.Scan()
	emailAddress := scanner.Text()
	
	// קראו את שם שולח ההתראות ב-SMS
	scanner.Scan()
	smsName := scanner.Text()
	
	// קראו את מספר הטלפון
	scanner.Scan()
	phoneNumber := scanner.Text()
	
	// קראו את הודעת ההתראה
	scanner.Scan()
	alertMessage := scanner.Text()
	
	// TODO: צרו EmailNotifier עם emailName ו-emailAddress
	
	// TODO: צרו SMSNotifier עם smsName ו-phoneNumber
	
	// TODO: השתמשו ב-SendAlert כדי לשלוח את alertMessage דרך שני שולחי ההתראות
	// והדפיסו את התוצאות
	
	// מנעו אזהרות על משתנים שאינם בשימוש (הסירו את השורות האלה כשתשתמשו במשתנים)
	_ = emailName
	_ = emailAddress
	_ = smsName
	_ = phoneNumber
	_ = alertMessage
}
quiz iconבחנו את עצמכם

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

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

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