مقدمة في الواجهات
جزء من قسم البرمجة كائنية التوجه في رحلة GO على Coddy. الدرس 25 من 107.
يعرّف interface في Go مجموعةً من توقيعات method من دون تنفيذها. وهو يصف ما يمكن لنوعٍ ما فعله، وليس كيفية فعله. وأي نوع ينفّذ جميع method الموجودة في interface يستوفي هذه interface تلقائيًا.
إليك كيفية تعريف interface:
type Speaker interface {
Speak() string
}تتطلب واجهة Speaker هذه أن يحتوي أي نوع ينفّذها على أسلوب Speak() يُرجع سلسلة نصية. والآن يمكن استخدام أي بنية تحتوي على هذا الأسلوب في أي موضع يُتوقَّع فيه وجود Speaker.
type Dog struct {
Name string
}
func (d Dog) Speak() string {
return d.Name + " says woof!"
}
type Cat struct {
Name string
}
func (c Cat) Speak() string {
return c.Name + " says meow!"
}كلٌّ من Dog وCat يطابقان الواجهة Speaker لأن كلاً منهما يمتلك أسلوب Speak() بالتوقيع الصحيح. يمكنك الآن كتابة دوال تقبل أي Speaker:
func MakeSound(s Speaker) {
fmt.Println(s.Speak())
}
func main() {
dog := Dog{Name: "Buddy"}
cat := Cat{Name: "Whiskers"}
MakeSound(dog) // بادي يقول ووف!
MakeSound(cat) // ويسكرز يقول مياو!
}تتيح لك interface كتابة شفرة مرنة وقابلة لإعادة الاستخدام تعمل مع any نوع يستوفي متطلبات interface، بغض النظر عن التنفيذ الأساسي.
التحدي
سهللنَبْنِ نظامًا لوصف المركبات يوضّح كيف تسمح الواجهات للأنواع المختلفة بمشاركة السلوك المشترك. ستنشئ واجهة يمكن لأنواع متعددة من المركبات تحقيقها، ثم تستخدمها لوصف أي مركبة بطريقة موحّدة.
ستنظّم التعليمات البرمجية عبر ملفين:
vehicles.go: عرّف واجهةDescriberذات method واحدة هيDescribe() string. ثم أنشئ بنيتين تحققان هذه الواجهة:Carمع حقليBrandوModel(وكلاهما من نوع string)Bicycleمع الحقلType(من نوع string) والحقلGears(من نوع int)
Describe()تُرجع string وصفيًا عن المركبة.main.go: أنشئ function باسمPrintDescriptionتقبل أيDescriberوتطبع نتيجة استدعاء methodDescribe()الخاصة بها. اقرأ معلومات المركبات من الإدخال، وأنشئ كلًا من Car وBicycle، واستخدم function الخاصة بك لطباعة وصف لكل منهما.
سيتم توفير المدخلات التالية:
- السطر 1: ماركة Car
- السطر 2: طراز Car
- السطر 3: نوع Bicycle
- السطر 4: عدد التروس (عدد صحيح)
يجب أن تُرجع methods Describe() السلاسل بالتنسيقين التاليين:
- Car:
[Brand] [Model] - Bicycle:
[Type] bike with [Gears] gears
على سبيل المثال، عند إعطاء Toyota وCamry وMountain و21، يجب أن يكون الناتج:
Toyota Camry
Mountain bike with 21 gearsالفكرة الأساسية هي أن function PrintDescription تعمل مع أي نوع يملك method باسم Describe(). ولا تحتاج إلى معرفة ما إذا كانت تتعامل مع Car أو Bicycle أو أي نوع مركبة آخر قد تضيفه لاحقًا.
جرّب بنفسك
package main
import (
"fmt"
)
// TODO: أنشئ دالة PrintDescription تقبل أي Describer
// وتطبع نتيجة استدعاء طريقة Describe() الخاصة بها
func main() {
// اقرأ المدخلات
var carBrand string
var carModel string
var bicycleType string
var gears int
fmt.Scanln(&carBrand)
fmt.Scanln(&carModel)
fmt.Scanln(&bicycleType)
fmt.Scanln(&gears)
// TODO: أنشئ Car بالماركة والموديل من المدخلات
// TODO: أنشئ Bicycle بالنوع والتروس من المدخلات
// TODO: استخدم PrintDescription لطباعة وصف السيارة
// TODO: استخدم PrintDescription لطباعة وصف الدراجة
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1أساسيات الـ OOP في Go
الملفات الخارجيةمساحة العمل والـ Modules في Goالـ Packages والـ Importsالأسماء المصدرة مقابل غير المصدرةمقدمة إلى الـ OOP في Goالـ Structs كـ Classesتعريف الـ Methods في الـ Structsالـ Pointer Receivers مقابل الـ Value Receiversتهيئة الـ Structدوال الـ Constructorمراجعة - آلة حاسبة بسيطة4الواجهات
مقدمة في الواجهاتالتنفيذ الضمنيالواجهة كعقدالواجهة الفارغة (any)تأكيد النوع (Type Assertion)تبديل النوع (Type Switch)تركيب الواجهاتواجهات Stringer و Errorمراجعة - حاسبة الأشكال7التغليف
الحقول المصدرة وغير المصدرةالتغليف على مستوى الحزمةدوال الـ Getter والـ Setterإخفاء المعلومات في Goملخص - سجلات الطلاب10الأنواع العامة (Go 1.18+)
مقدمة في الأنواع العامةمعاملات الأنواعقيود الأنواعالـ Structs العامةحل بديل للـ Methods العامةملخص - المجموعات العامة13أنماط التصميم - الجزء الأول
مقدمة في أنماط التصميمنمط Singletonنمط Factoryنمط Abstract Factoryنمط Observerنمط Strategy2تعمق في الأنواع و Structs
الأنواع الأساسية والمركبةتعريفات الأنواع المخصصةStruct TagsStructs مجهولةStructs متداخلةالقيم الصفرية والافتراضيةمراجعة - دفتر العناوين5التركيب بدلاً من الوراثة
لماذا لا تدعم Go الوراثةأساسيات تضمين الـ Structترقية الـ Methodتضمين عدة Structsالتضمين مقابل التجميعحجب الـ Methods المضمنةملخص - الهيكل الهرمي للموظفين8معالجة الأخطاء و OOP
واجهة errorأنواع الأخطاء المخصصةتغليف الأخطاء (fmt.Errorf)أخطاء Sentinelerrors.Is() و errors.As()Panic و Defer و Recoverملخص - File Parser11المكتبة القياسية والبرمجة كائنية التوجه (OOP)
io.Reader و io.Writerواجهة sort.Interfaceواجهة fmt.Stringerencoding/json مع Structsواجهة http.Handlerمراجعة - نماذج REST API14أنماط التصميم - الجزء الثاني
نمط الأمرنمط المحولنمط المزيننمط طريقة القالبنمط الحالةنمط التركيبMiddleware كنمط مزين3المؤشرات والذاكرة
أساسيات المؤشرات في Goالمؤشرات إلى الـ Structsالتمرير بالقيمة مقابل التمرير بالمرجعدالة ()newGarbage Collection في Goملخص - بناء Linked List6تعدد الأشكال في Go
تعدد الأشكال عبر InterfacesDuck Typing في Goقواعد استيفاء الـ Interfaceمجموعات متعددة الأشكالحقن التبعيةمراجعة - معالج الدفع9التزامن والبرمجة كائنية التوجه (OOP)
أساسيات الـ Goroutinesالقنوات (Channels) والاتصالالقنوات المخزنة (Buffered) مقابل غير المخزنةجملة Selectsync.Mutex و sync.RWMutexsync.WaitGroupتصميم الـ Structs الآمنة للخيوط (Thread-Safe)مراجعة - Worker Poolتدرّب بنفسك: مترجم Go عبر الإنترنت