Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

ترقية الـ Method

جزء من قسم Object Oriented Programming في رحلة GO على Coddy — الدرس 36 من 107.

تماماً كما يؤدي تضمين الـ struct إلى ترقية الحقول إلى الـ struct الخارجي، تقوم لغة Go أيضاً بترقية الأساليب (methods) من الأنواع المضمنة. وهذا يعني أنه يمكنك استدعاء الأساليب المعرفة في الـ 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())  // تعمل أيضًا
}

لهذه الترقية نتيجة مهمة بالنسبة للواجهات (interfaces). إذا كان النوع المضمن (embedded type) يحقق واجهة معينة، فإن النوع الخارجي يحققها تلقائياً أيضاً:

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 بشكل صريح أبداً، ومع ذلك فإنه يستوفي الواجهة (interface) لأن Engine المضمن لديه الطريقة (method) المطلوبة. هذه هي الطريقة التي تحقق بها لغة Go إعادة استخدام السلوك دون الوراثة التقليدية.

challenge icon

التحدي

سهل

لنقم ببناء نظام مشغل موسيقى يوضح كيف يتم ترقية (promote) الأساليب (methods) من الأنواع المضمنة (embedded types) إلى النوع الخارجي، وكيف يتيح ذلك تحقيق الواجهات (interfaces) من خلال التركيب (composition).

ستقوم بتنظيم الكود الخاص بك عبر ملفين:

  • audio.go: قم بإنشاء اللبنات الأساسية لمشغل الموسيقى الخاص بك:
    • هيكل AudioPlayer مع حقل Brand (string) وطريقة 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: اسم طراز Smartphone
  • السطر 2: العلامة التجارية للصوت في Smartphone
  • السطر 3: اسم طراز Tablet
  • السطر 4: العلامة التجارية للصوت في Tablet

لكل جهاز، اطبع طرازه متبوعًا بنتيجة تمريره إلى 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 دون أي كود إضافي.

ورقة مرجعية

عندما تقوم بنية (struct) بتضمين نوع آخر، يتم ترقية الأساليب (methods) من النوع المضمن تلقائياً إلى البنية الخارجية:

type Engine struct {
    Horsepower int
}

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

type Car struct {
    Model string
    Engine  // embedded
}

func main() {
    c := Car{
        Model:  "Sedan",
        Engine: Engine{Horsepower: 200},
    }
    
    fmt.Println(c.Start())         // Engine started
    fmt.Println(c.Engine.Start())  // يعمل أيضاً
}

إذا كان النوع المضمن يستوفي واجهة (interface)، فإن النوع الخارجي يستوفيها تلقائياً أيضاً:

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
}

يتيح ذلك إعادة استخدام السلوك من خلال التركيب (composition) بدون الوراثة التقليدية.

جرّب بنفسك

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اختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس Object Oriented Programming