Menu
CoddyTech

مجموعات متعددة الأشكال

جزء من قسم البرمجة كائنية التوجه في رحلة GO على Coddy. الدرس 44 من 107.

من أقوى استخدامات الواجهات تخزين أنواع مختلفة في المجموعة نفسها. يمكن لشريحة من نوع واجهة أن تحتوي على أي قيمة تستوفي شروط تلك الواجهة، مما يتيح لك تجميع أنواع مختلفة لكنها مترابطة معًا.

تخيّل موقفًا تحتاج فيه إلى إدارة أشكال متنوعة. بدلًا من استخدام شرائح منفصلة لكل نوع، يمكنك استخدام شريحة واحدة من نوع الواجهة:

type Shape interface {
    Area() float64
}

type Circle struct{ Radius float64 }
func (c Circle) Area() float64 { return 3.14159 * c.Radius * c.Radius }

type Rectangle struct{ Width, Height float64 }
func (r Rectangle) Area() float64 { return r.Width * r.Height }

func main() {
    shapes := []Shape{
        Circle{Radius: 5},
        Rectangle{Width: 4, Height: 3},
        Circle{Radius: 2},
    }
    
    for _, s := range shapes {
        fmt.Printf("Area: %.2f\n", s.Area())
    }
}

تحتوي الشريحة shapes على دوائر ومستطيلات. عند التكرار، يستجيب كل عنصر وفقًا لنوعه الفعلي عند استدعاء Area(). هذا هو تعدد الأشكال مطبقًا على المجموعات: تتعامل الحلقة نفسها مع جميع أنواع الأشكال بطريقة موحدة.

تُعدّ المجموعات متعددة الأشكال ضرورية عند بناء أنظمة تعالج عناصر متنوعة: كنظام إشعارات يرسل رسائل البريد الإلكتروني والرسائل النصية القصيرة، أو لعبة تحدّث أنواعًا مختلفة من الأعداء، أو معالج مستندات يتعامل مع تنسيقات ملفات متعددة. لا تهتم المجموعة بالأنواع المحددة، بل يكفي أن يوفّر كل عنصر السلوك المطلوب.

challenge icon

التحدي

سهل

لنبنِ نظامًا لإدارة المهام يتعامل مع أنواع مختلفة من المهام من خلال واجهة موحّدة. ستنشئ أنواعًا متنوعة من المهام وتعالجها جميعًا معًا ضمن مجموعة متعددة الأشكال.

ستنظّم الشيفرة عبر ثلاثة ملفات:

  • task.go: عرّف واجهة Task التي تتطلب الأسلوب Summary() string. ستكون هذه الواجهة العقد المشترك الذي يجب أن تلتزم به جميع أنواع المهام.
  • types.go: أنشئ ثلاثة أنواع مختلفة من المهام، يطبّق كل منها الواجهة Task:
    • BugFix بحقلَي ID (string) وSeverity (string). تُرجع Summary() القيمة Bug #[ID] ([Severity])
    • Feature بحقلَي Name (string) وPoints (int). تُرجع Summary() القيمة Feature: [Name] - [Points] pts
    • Documentation بحقل Topic (string). تُرجع Summary() القيمة Docs: [Topic]
  • main.go: أنشئ دالة باسم PrintBacklog تستقبل شريحة من Task وتطبع ملخص كل مهمة في سطر مستقل. اقرأ تفاصيل المهام من الإدخال، وأنشئ مهمة واحدة من كل نوع، واجمعها كلها في شريحة واحدة من نوع []Task، ثم مرّرها إلى PrintBacklog.

ستُقدَّم المدخلات التالية:

  • السطر 1: معرّف الخطأ
  • السطر 2: درجة خطورة الخطأ
  • السطر 3: اسم الميزة
  • السطر 4: نقاط الميزة (عدد صحيح)
  • السطر 5: موضوع التوثيق

على سبيل المثال، إذا أُعطيت القيم 1042 وcritical وThemes و8 وAPI، فينبغي أن يكون الناتج:

Bug #1042 (critical)
Feature: Themes - 8 pts
Docs: API

تكمن الفائدة هنا في أن PrintBacklog لا يحتاج إلى منطق منفصل للأخطاء أو الميزات أو التوثيق. فهو يمرّ ببساطة على الشريحة ويستدعي Summary() لكل عنصر. ويستجيب كل نوع من المهام بتنسيقه الخاص، موضحًا كيف تتيح لك المجموعات متعددة الأشكال معالجة أنواع متنوعة بطريقة موحّدة.

جرّب بنفسك

package main

import (
	"fmt"
)

// TODO: أنشئ دالة PrintBacklog تقبل شريحة من Task
// وتطبع ملخص كل مهمة في سطر مستقل

func main() {
	// اقرأ المدخلات
	var bugID string
	var bugSeverity string
	var featureName string
	var featurePoints int
	var docTopic string

	fmt.Scanln(&bugID)
	fmt.Scanln(&bugSeverity)
	fmt.Scanln(&featureName)
	fmt.Scanln(&featurePoints)
	fmt.Scanln(&docTopic)

	// TODO: أنشئ مهمة واحدة من كل نوع (BugFix, Feature, Documentation)

	// TODO: اجمع كل المهام في شريحة []Task واحدة

	// TODO: استدعِ PrintBacklog مع شريحة المهام
}
quiz iconاختبر نفسك

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

جميع دروس البرمجة كائنية التوجه

تدرّب بنفسك: مترجم Go عبر الإنترنت