الانتقال إلى المحتوى الرئيسي
الوحدة 6 · الدرس 1 من 526/50 في الدورة~12 min
دروس الوحدة (1/5)

واجهات: تحديد السلوك

الواجهة في Go عبارة عن مجموعة من توقيعات الطريقة. قيمة ينفذ الواجهة إذا كانت تحتوي على جميع تلك الأساليب — لا implements، لا extends، لا يوجد تسجيل صريح. انها يُطلق على النموذج غالبًا "الكتابة الهيكلية" أو "كتابة البطة الثابتة": يتحقق المترجم من المطابقة في وقت الترجمة، ولكن بناءً على ذلك الشكل وليس على التصريحات.

الإعلان عن واجهة

Go
type Greeter interface {
    Greet() string
}

الاصطلاح: الأسماء التي تنتهي بـ -er للواجهات ذات الطريقة الواحدة (Reader، Writer، Stringer، Closer). واجهات صغيرة (الطرق 1-2) ** اصطلاحية **: المكتبة القياسية مليئة بـ واجهات صغيرة يتم تجميعها معًا (io.ReadWriter، محمي_INLINE_9،...).

التنفيذ الضمني

Go
type Person struct{ Name string }

func (p Person) Greet() string {
    return "ciao " + p.Name
}

// Person satisfies Greeter because it has the required method.
var s Greeter = Person{Name: "Ada"}
fmt.Println(s.Greet())

لا توجد كلمة رئيسية. إذا كان النوع يحتوي على الأساليب، فيمكن تخصيصه له متغير من هذا النوع من الواجهة. هذا كل شيء.

تعدد الأشكال عبر الواجهة

Go
type Robot struct{ ID string }
func (r Robot) Greet() string { return "bip " + r.ID }

func greet(s Greeter) {
    fmt.Println(s.Greet())
}

greet(Person{Name: "Ada"})
greet(Robot{ID: "R2"})

greet يقبل أي نوع يرضي Greeter. هذا هو الطريق الذهاب للقيام بتعدد الأشكال: لا يوجد تسلسلات هرمية، فقط القدرة.

الواجهة الفارغة

Go
var x interface{} = 42
var y any = "ciao"   // any is the built-in alias of interface{}

interface{} (أو any منذ Go 1.18) لا يتطلب أي طرق، لذا فإن أي القيمة تفي به. مفيدة للحاويات العامة، ولكن لاستخراج القيمة المحددة التي تحتاجها تأكيد النوع أو مفتاح النوع (الدروس القادمة).

مجموعة الطريقة: القيمة مقابل مستقبل المؤشر (معاينة)

الاستدعاء من الوحدة 5:

  • الطرق التي تحتوي على مستقبل القيمة موجودة في مجموعة الطرق لكل من T و*T.
  • الأساليب التي تحتوي على مستقبل المؤشر موجودة فقط في مجموعة الأساليب *T.

النتيجة العملية:

Go
type Counter struct{ N int }
func (c *Counter) Inc() { c.N++ }

type Incrementer interface { Inc() }

var i Incrementer = &Counter{}   // OK: *Counter has Inc()
// var j Incrementer = Counter{} // ERROR: Counter (value) does NOT

عندما تحتوي الطريقة على جهاز استقبال مؤشر، يجب عليك تعيين مؤشر له متغير الواجهة

جربه

تمرين#go.m6.l1.e1
المحاولات: 0جارٍ التحميل…

تعريف واجهة Greeter باستخدام سلسلة Greet()‎ ذات أسلوب واحد.

جارٍ تحميل المحرر…
إظهار التلميح

بناء الجملة: `اكتب اسم الواجهة {طريقة (وسائط) إرجاع }`.

الحل متاح بعد 3 من المحاولات

تمرين#go.m6.l1.e2
المحاولات: 0جارٍ التحميل…

تنفيذ Greeter على نوع جديد من الروبوتات بسلسلة معرف الحقل؛ تقوم الطريقة بإرجاع "bip" + ID.

جارٍ تحميل المحرر…
إظهار التلميح

لا توجد "أدوات": ما عليك سوى تحديد الطريقة باستخدام التوقيع الصحيح.

الحل متاح بعد 3 من المحاولات

Quiz#go.m6.l1.e3
جاهز

كيف تعلن أن النوع P ينفذ واجهة Greeter؟

Go
type P struct{}
// ?
خيارات الإجابة

خلاصة

  • الواجهة = مجموعة توقيعات الطريقة؛ لا محمي_INLINE_17.
  • التنفيذ الضمني: ما عليك سوى استخدام الأساليب ذات التوقيع الصحيح.
  • اصطلاحي: واجهات صغيرة (طرق 1-2)، الأسماء في -er.
  • interface{} / any: يقبل أي قيمة، ويفقد أمان النوع.
  • مجموعة الطريقة: جهاز استقبال المؤشر → فقط *T يفي بالواجهة.
  • تعدد الأشكال: معلمات من نوع الواجهة، بدون تسلسلات هرمية.