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

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

جزء من قسم البرمجة كائنية التوجه في رحلة 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() وفقًا لنوعه الفعلي. هذا هو تعدد الأشكال مطبقًا على المجموعات: تتعامل الحلقة نفسها مع جميع أنواع الأشكال بشكل موحّد.

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

challenge icon

التحدي

سهل

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

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

  • task.go: عرّف واجهة Task تتطلب method باسم Summary() string. ستكون هذه الواجهة هي contract common الذي يجب على جميع أنواع المهام fulfillه.
  • 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: أنشئ function باسم PrintBacklog تقبل شريحة من Task وتطبع ملخص كل مهمة في سطر مستقل. اقرأ تفاصيل المهام من الإدخال، وأنشئ مهمة واحدة من كل نوع، واجمعها كلها في شريحة واحدة من نوع []Task، ثم مرّرها إلى PrintBacklog.

ستُوفَّر المدخلات التالية:

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

على سبيل المثال، عند إعطاء 1042 وcritical وDark Mode و8 وAPI Reference، يجب أن يكون الناتج:

Bug #1042 (critical)
Feature: Dark Mode - 8 pts
Docs: API Reference

تكمن القوة هنا في أن PrintBacklog لا يحتاج إلى منطق منفصل للتعامل مع Bug أو Feature أو Documentation. فهو يكرّر ببساطة عبر الشريحة ويستدعي 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 عبر الإنترنت