دروس الوحدة (1/5)
واجهات: تحديد السلوك
الواجهة في Go عبارة عن مجموعة من توقيعات الطريقة. قيمة
ينفذ الواجهة إذا كانت تحتوي على جميع تلك الأساليب — لا
implements، لا extends، لا يوجد تسجيل صريح. انها
يُطلق على النموذج غالبًا "الكتابة الهيكلية" أو "كتابة البطة الثابتة":
يتحقق المترجم من المطابقة في وقت الترجمة، ولكن بناءً على ذلك
الشكل وليس على التصريحات.
الإعلان عن واجهة
type Greeter interface {
Greet() string
}الاصطلاح: الأسماء التي تنتهي بـ -er للواجهات ذات الطريقة الواحدة
(Reader، Writer، Stringer، Closer). واجهات صغيرة
(الطرق 1-2) ** اصطلاحية **: المكتبة القياسية مليئة بـ
واجهات صغيرة يتم تجميعها معًا (io.ReadWriter،
محمي_INLINE_9،...).
التنفيذ الضمني
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())لا توجد كلمة رئيسية. إذا كان النوع يحتوي على الأساليب، فيمكن تخصيصه له متغير من هذا النوع من الواجهة. هذا كل شيء.
تعدد الأشكال عبر الواجهة
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. هذا هو الطريق الذهاب
للقيام بتعدد الأشكال: لا يوجد تسلسلات هرمية، فقط القدرة.
الواجهة الفارغة
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.
النتيجة العملية:
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عندما تحتوي الطريقة على جهاز استقبال مؤشر، يجب عليك تعيين مؤشر له متغير الواجهة
جربه
تعريف واجهة Greeter باستخدام سلسلة Greet() ذات أسلوب واحد.
إظهار التلميح
بناء الجملة: `اكتب اسم الواجهة {طريقة (وسائط) إرجاع }`.
الحل متاح بعد 3 من المحاولات
تنفيذ Greeter على نوع جديد من الروبوتات بسلسلة معرف الحقل؛ تقوم الطريقة بإرجاع "bip" + ID.
إظهار التلميح
لا توجد "أدوات": ما عليك سوى تحديد الطريقة باستخدام التوقيع الصحيح.
الحل متاح بعد 3 من المحاولات
كيف تعلن أن النوع P ينفذ واجهة Greeter؟
type P struct{}
// ?خلاصة
- الواجهة = مجموعة توقيعات الطريقة؛ لا محمي_INLINE_17.
- التنفيذ الضمني: ما عليك سوى استخدام الأساليب ذات التوقيع الصحيح.
- اصطلاحي: واجهات صغيرة (طرق 1-2)، الأسماء في
-er. interface{}/any: يقبل أي قيمة، ويفقد أمان النوع.- مجموعة الطريقة: جهاز استقبال المؤشر → فقط
*Tيفي بالواجهة. - تعدد الأشكال: معلمات من نوع الواجهة، بدون تسلسلات هرمية.