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

واجهة sort.Interface

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

توفر حزمة sort مثالًا ممتازًا آخر على التصميم القائم على الواجهات. لفرز مجموعة مخصّصة، يجب أن ينفّذ نوعك sort.Interface:

type Interface interface {
    Len() int
    Less(i, j int) bool
    Swap(i, j int)
}

تمنح هذه الأساليب خوارزمية الفرز كل ما تحتاج إليه: طول collection، وطريقة لمقارنة elements، وطريقة لتبديلها. إليك كيفية جعل شريحة من البنى المخصصة قابلة للفرز:

type Person struct {
    Name string
    Age  int
}

type ByAge []Person

func (a ByAge) Len() int           { return len(a) }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
func (a ByAge) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }

func main() {
    people := []Person{
        {"Alice", 30},
        {"Bob", 25},
        {"Carol", 35},
    }
    
    sort.Sort(ByAge(people))
    fmt.Println(people)
    // [{Bob 25} {Alice 30} {Carol 35}]
}

تتمثل الفكرة الأساسية في إنشاء نوع مُسمّى (ByAge) استنادًا إلى شريحتك. يتيح لك ذلك تعريف سلوكيات فرز مختلفة للبيانات نفسها. يمكنك إنشاء ByName مع تنفيذ مختلف لـ Less للفرز أبجديًا بدلًا من ذلك.

بمجرد أن يفي نوعك بالواجهة sort.Interface، فإنه يعمل تلقائيًا مع sort.Sort() وsort.Reverse() وsort.IsSorted().

challenge icon

التحدي

سهل

لنَبْنِ نظامًا قابلًا للفرز لمخزون المنتجات يوضّح قوة sort.Interface في Go! ستنشئ نوع Product وتنفّذ استراتيجيات فرز متعددة، مما يسمح بفرز المجموعة نفسها بطرق مختلفة.

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

  • product.go: عرّف نوع المنتج وتنفيذات الفرز الخاصة به.

    أنشئ بنية Product بثلاثة حقول: Name (من النوع string)، وPrice (من النوع float64)، وQuantity (من النوع int).

    أنشئ نوعين مُسمّيين بالاعتماد على []Product:

    • ByPrice - لفرز المنتجات حسب السعر بترتيب تصاعدي
    • ByQuantity - لفرز المنتجات حسب الكمية بترتيب تنازلي (الكمية الأكبر أولًا)

    يحتاج كل نوع إلى تنفيذ الأساليب الثلاثة المطلوبة بواسطة sort.Interface: Len()، وLess(i, j int)، وSwap(i, j int). يحدّد الأسلوب Less ترتيب الفرز لكل نوع.

  • main.go: أنشئ مخزون المنتجات وفرزه.

    اقرأ وضع الفرز (price أو quantity)، ثم اقرأ العدد متبوعًا بتفاصيل المنتجات. يُقدَّم كل منتج في ثلاثة أسطر: الاسم، والسعر، والكمية.

    أنشئ شريحة من المنتجات، وفرزها باستخدام نوع الفرز المناسب بناءً على الوضع، ثم اطبع كل منتج بهذا التنسيق:

    [Name]: $[Price] (x[Quantity])

    اعرض الأسعار بمنزلتين عشريتين.

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

  • السطر 1: وضع الفرز (price أو quantity)
  • السطر 2: عدد المنتجات
  • الأسطر التالية: تفاصيل المنتج (الاسم، والسعر، والكمية - ثلاثة أسطر لكل منتج)

على سبيل المثال، عند إعطاء:

price
3
Laptop
999.99
5
Mouse
29.99
50
Keyboard
79.99
25

ينبغي أن يكون الناتج:

Mouse: $29.99 (x50)
Keyboard: $79.99 (x25)
Laptop: $999.99 (x5)

وعند إعطاء:

quantity
3
Laptop
999.99
5
Mouse
29.99
50
Keyboard
79.99
25

ينبغي أن يكون الناتج:

Mouse: $29.99 (x50)
Keyboard: $79.99 (x25)
Laptop: $999.99 (x5)

لاحظ كيف يمكن فرز بيانات المنتج نفسها بطرق مختلفة بمجرد استخدام نوع مُسمّى مختلف. وبمجرد أن تستوفي أنواعك متطلبات sort.Interface، فإنها تعمل بسلاسة مع sort.Sort() من المكتبة القياسية.

جرّب بنفسك

package main

import (
	"bufio"
	"fmt"
	"os"
	"sort"
	"strconv"
	"strings"
)

func main() {
	reader := bufio.NewReader(os.Stdin)

	// اقرأ وضع الترتيب
	var mode string
	fmt.Fscanln(reader, &mode)

	// اقرأ عدد المنتجات
	var count int
	fmt.Fscanln(reader, &count)

	// اقرأ المنتجات
	products := make([]Product, count)
	for i := 0; i < count; i++ {
		name, _ := reader.ReadString('\n')
		name = strings.TrimSpace(name)

		priceStr, _ := reader.ReadString('\n')
		priceStr = strings.TrimSpace(priceStr)
		price, _ := strconv.ParseFloat(priceStr, 64)

		qtyStr, _ := reader.ReadString('\n')
		qtyStr = strings.TrimSpace(qtyStr)
		quantity, _ := strconv.Atoi(qtyStr)

		products[i] = Product{Name: name, Price: price, Quantity: quantity}
	}

	// TODO: رتّب المنتجات بناءً على الوضع
	// إذا كان الوضع هو "price"، استخدم النوع ByPrice
	// إذا كان الوضع هو "quantity"، استخدم النوع ByQuantity
	// استخدم sort.Sort() مع النوع المناسب

	// TODO: اطبع كل منتج بالتنسيق:
	// [Name]: $[Price] (x[Quantity])
	// استخدم fmt.Printf مع %.2f لتنسيق السعر
}
quiz iconاختبر نفسك

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

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

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