Menu
Coddy logo textTech

קידום מתודות

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

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

type Engine struct {
    Horsepower int
}

func (e Engine) Start() string {
    return "Engine started"
}

type Car struct {
    Model string
    Engine  // מוטמע
}

מכיוון ש־Car מכיל את Engine, המתודה Start() מקודמת אוטומטית:

func main() {
    c := Car{
        Model:  "Sedan",
        Engine: Engine{Horsepower: 200},
    }
    
    fmt.Println(c.Start())         // המנוע הופעל
    fmt.Println(c.Engine.Start())  // גם עובד
}

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

type Starter interface {
    Start() string
}

func Ignite(s Starter) {
    fmt.Println(s.Start())
}

func main() {
    c := Car{Model: "Sedan", Engine: Engine{Horsepower: 200}}
    Ignite(c)  // Car מממשת את Starter באמצעות Engine
}

הטיפוס Car לעולם אינו מממש במפורש את Starter, אך הוא עומד בדרישות הממשק משום של-Engine המשולב בו יש את המתודה הנדרשת. כך Go מאפשרת שימוש חוזר בהתנהגות ללא ירושה מסורתית.

challenge icon

אתגר

קל

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

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

  • audio.go: צרו את אבני הבניין של נגן המוזיקה שלכם:
    • מבנה AudioPlayer עם שדה Brand (מחרוזת) ושיטה Play() string שמחזירה [Brand] playing audio
    • ממשק Playable שדורש שיטה Play() string
    • מבנה Smartphone עם שדה Model שמטמיע את AudioPlayer
    • מבנה Tablet עם שדה Model שמטמיע את AudioPlayer
  • main.go: צרו פונקציה בשם StartPlayback שמקבלת כל ערך שמקיים את הממשק Playable ומחזירה את התוצאה של קריאה ל־Play(). קראו את פרטי המכשירים מהקלט, צרו גם Smartphone וגם Tablet, והדגימו ששניהם מקיימים את הממשק Playable באמצעות AudioPlayer המוטמע בהם, אף על פי שאף אחד מהטיפוסים אינו מממש בעצמו את Play() במפורש.

הקלט הבא יסופק:

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

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

לדוגמה, בהינתן iPhone 15, Apple Audio, iPad Pro ו־Beats, הפלט שלכם אמור להיות:

iPhone 15
Apple Audio playing audio
iPad Pro
Beats playing audio

שימו לב שאפשר להעביר גם את Smartphone וגם את Tablet אל StartPlayback, מכיוון שהשיטה Play() של AudioPlayer מקודמת אוטומטית לכל אחד מהטיפוסים החיצוניים, וכך הם מקיימים את הממשק Playable ללא צורך בקוד נוסף.

נסו בעצמכם

package main

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

// TODO: צרו פונקציה בשם StartPlayback שמקבלת כל ערך מסוג Playable
// ומחזירה את התוצאה של הקריאה ל-Play()

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	
	// קראו את דגם הסמארטפון
	scanner.Scan()
	smartphoneModel := scanner.Text()
	
	// קראו את מותג השמע של הסמארטפון
	scanner.Scan()
	smartphoneBrand := scanner.Text()
	
	// קראו את דגם הטאבלט
	scanner.Scan()
	tabletModel := scanner.Text()
	
	// קראו את מותג השמע של הטאבלט
	scanner.Scan()
	tabletBrand := scanner.Text()
	
	// TODO: צרו Smartphone עם AudioPlayer מוטמע
	
	// TODO: צרו Tablet עם AudioPlayer מוטמע
	
	// TODO: הדפיסו את דגם הסמארטפון, ואז קראו ל-StartPlayback עם הסמארטפון
	
	// TODO: הדפיסו את דגם הטאבלט, ואז קראו ל-StartPlayback עם הטאבלט
	
	_ = smartphoneModel
	_ = smartphoneBrand
	_ = tabletModel
	_ = tabletBrand
	fmt.Println("TODO: Complete the implementation")
}
quiz iconבחנו את עצמכם

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

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

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