Menu
Coddy logo textTech

הסתרת מתודות מוטמעות

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

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

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

type Animal struct {
    Name string
}

func (a Animal) Speak() string {
    return "Some sound"
}

type Dog struct {
    Animal
    Breed string
}

func (d Dog) Speak() string {
    return "Woof!"
}

כעת, כשאתה קורא ל־Speak() על Dog, נעשה שימוש במתודה החיצונית:

func main() {
    d := Dog{Animal: Animal{Name: "Rex"}, Breed: "Labrador"}
    
    fmt.Println(d.Speak())        // Woof! - המתודה של Dog
    fmt.Println(d.Animal.Speak()) // Some sound - המתודה של Animal
}

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

func (d Dog) Speak() string {
    return d.Animal.Speak() + " (but actually Woof!)"
}

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

challenge icon

אתגר

קל

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

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

  • base.go: צרו struct בשם BaseNotification עם השדות Title ו-Priority (שניהם מחרוזות). הוסיפו לו מתודה בשם Format() string שמחזירה את ההתראה בפורמט אחיד: [Priority] Title.
  • channels.go: צרו שני סוגים של ערוצי התראות שמטמיעים את BaseNotification ומצלילים את המתודה Format באמצעות מימושים משלהם:
    • EmailNotification עם שדה Recipient. המתודה Format() שלה צריכה להחזיר Email to [Recipient]: [Priority] Title
    • SlackNotification עם שדה Channel. המתודה Format() שלה צריכה לקרוא למתודה המוטמעת BaseNotification.Format() ולהוסיף לפני התוצאה את #[Channel]:
  • main.go: קראו את פרטי ההתראות מהקלט, צרו את שני סוגי ההתראות והדגימו הצללה באמצעות הדפסה של:
    1. הפלט המעוצב של EmailNotification (באמצעות המתודה המוצללת שלו)
    2. פורמט הבסיס של EmailNotification (באמצעות קריאה מפורשת למתודה המוטמעת)
    3. הפלט המעוצב של SlackNotification (שמשתמשת פנימית במתודת הבסיס)

הקלט שיסופק יהיה:

  • שורה 1: כותרת ההתראה
  • שורה 2: רמת העדיפות
  • שורה 3: נמען האימייל
  • שורה 4: שם ערוץ Slack

לדוגמה, עבור Server Alert, HIGH, admin@company.com ו-ops-alerts, הפלט שלכם צריך להיות:

Email to admin@company.com: HIGH Server Alert
[HIGH] Server Alert
#ops-alerts: [HIGH] Server Alert

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

נסו בעצמכם

package main

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

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	
	// קרא את כותרת ההתראה
	scanner.Scan()
	title := scanner.Text()
	
	// קרא את רמת העדיפות
	scanner.Scan()
	priority := scanner.Text()
	
	// קרא את נמען הדוא״ל
	scanner.Scan()
	recipient := scanner.Text()
	
	// קרא את שם הערוץ ב-Slack
	scanner.Scan()
	channel := scanner.Text()
	
	// TODO: צור EmailNotification עם התראת הבסיס, הכותרת, העדיפות והנמען
	
	// TODO: צור SlackNotification עם התראת הבסיס, הכותרת, העדיפות והערוץ
	
	// TODO: הדפס את הפלט המעוצב של EmailNotification (באמצעות המתודה שלו שמסתירה את מתודת הבסיס)
	
	// TODO: הדפס את פורמט הבסיס של EmailNotification (באמצעות קריאה מפורשת למתודה המוטמעת)
	
	// TODO: הדפס את הפלט המעוצב של SlackNotification
	
	fmt.Println() // מציין מקום - הסר בעת המימוש
}
quiz iconבחנו את עצמכם

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

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

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