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

مقدمة في الأنواع العامة

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

قبل Go 1.18، كانت كتابة تعليمات برمجية قابلة لإعادة الاستخدام لأنواع مختلفة تعني إما تكرار الدوال أو استخدام الواجهة الفارغة any مع تأكيدات النوع. تحل الأنواع العامة هذه المشكلة من خلال السماح لك بكتابة دوال وأنواع تعمل مع أنواع متعددة، مع الحفاظ على أمان النوع الكامل.

فكّر في العثور على القيمة minimum في slice. من دون استخدام الأنواع العامة، ستحتاج إلى دوال منفصلة لكل type:

func MinInt(values []int) int {
    min := values[0]
    for _, v := range values {
        if v < min {
            min = v
        }
    }
    return min
}

func MinFloat64(values []float64) float64 {
    min := values[0]
    for _, v := range values {
        if v < min {
            min = v
        }
    }
    return min
}

باستخدام الأنواع العامة، تكتب المنطق مرة واحدة باستخدام type parameter بين قوسين مربعين:

func Min[T int | float64](values []T) T {
    min := values[0]
    for _, v := range values {
        if v < min {
            min = v
        }
    }
    return min
}

يُعلن [T int | float64] عن مُعامل نوع T يمكن أن يكون إما int أو float64. الآن يمكنك استدعاء Min([]int{3, 1, 2}) أو Min([]float64{3.5, 1.2}) باستخدام الدالة نفسها. يتحقق المصرّف من الأنواع في وقت الترجمة، لذا تحصل على الأمان من دون تكلفة إضافية أثناء وقت التشغيل.

في الدروس القادمة، سنستكشف معلمات النوع والقيود والبُنى generic بالتفصيل.

challenge icon

التحدي

سهل

لنَبْنِ محللًا للنتائج يعمل مع النتائج الصحيحة والعشرية باستخدام generic! ستنشئ function generic واحدة يمكنها إيجاد maximum في slice، مما يلغي الحاجة إلى code مكرر للأنواع العددية المختلفة.

ستنظم code عبر ملفين:

  • analyzer.go: عرّف function التحليل generic.

    أنشئ function generic Max[T int | float64](values []T) T التي تجد وتعيد maximum في slice. يجب أن تعمل function مع نوعي int وfloat64 من خلال parameter النوع T.

    أنشئ أيضًا function generic Sum[T int | float64](values []T) T التي تحسب وتعيد مجموع كل values في slice.

  • main.go: اقرأ الإدخال واعرض functions generic الخاصة بك مع أنواع مختلفة.

    اقرأ مؤشر type (int أو float)، ثم اقرأ count متبوعًا بهذا العدد من values. حلّل values وفقًا لـ type، واستدعِ كلًا من Max وSum باستخدام type المناسب، ثم اطبع النتائج.

    بالنسبة إلى إدخال integer، اطبع:

    Max (int): [value]
    Sum (int): [value]

    بالنسبة إلى إدخال float، اطبع مع منزلة عشرية واحدة:

    Max (float): [value]
    Sum (float): [value]

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

  • السطر 1: مؤشر type (int أو float)
  • السطر 2: عدد values (integer)
  • الأسطر التالية: value واحدة في كل سطر

على سبيل المثال، إذا كان الإدخال:

int
4
15
8
23
11

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

Max (int): 23
Sum (int): 57

وإذا كان الإدخال:

float
3
4.5
9.2
6.8

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

Max (float): 9.2
Sum (float): 20.5

لاحظ كيف تتعامل functions generic نفسها مع البيانات الصحيحة والعشرية: إذ يسمح parameter النوع [T int | float64] للمترجم بإنشاء code آمن من حيث النوع لكل استخدام، بينما تكتب المنطق مرة واحدة فقط.

جرّب بنفسك

package main

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

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

	// اقرأ مؤشر النوع
	typeStr, _ := reader.ReadString('\n')
	typeStr = strings.TrimSpace(typeStr)

	// اقرأ العدد
	countStr, _ := reader.ReadString('\n')
	count, _ := strconv.Atoi(strings.TrimSpace(countStr))

	if typeStr == "int" {
		// اقرأ قيم الأعداد الصحيحة
		values := make([]int, count)
		for i := 0; i < count; i++ {
			line, _ := reader.ReadString('\n')
			values[i], _ = strconv.Atoi(strings.TrimSpace(line))
		}

		// TODO: استدعِ Max و Sum مع شريحة الأعداد الصحيحة
		// TODO: اطبع النتائج بالتنسيق "Max (int): [value]" و "Sum (int): [value]"

	} else if typeStr == "float" {
		// اقرأ قيم الأعداد العشرية
		values := make([]float64, count)
		for i := 0; i < count; i++ {
			line, _ := reader.ReadString('\n')
			values[i], _ = strconv.ParseFloat(strings.TrimSpace(line), 64)
		}

		// TODO: استدعِ Max و Sum مع شريحة float64
		// TODO: اطبع النتائج بمنزلة عشرية واحدة بالتنسيق "Max (float): [value]" و "Sum (float): [value]"
	}
}
quiz iconاختبر نفسك

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

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

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