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

تسلسل الدوال (Method Chaining)

جزء من قسم Object Oriented Programming في رحلة GO على Coddy — الدرس 81 من 107.

تسلسل الأساليب (Method chaining) هي تقنية تعيد فيها الأساليب الكائن المستلم (receiver)، مما يسمح بربط استدعاءات متعددة للأساليب معاً في عبارة واحدة. لقد رأيت هذا بالفعل في نمط الباني (Builder pattern)، ولكنه مفهوم مستقل مفيد في سياقات عديدة.

المفتاح هو إرجاع مؤشر إلى الـ struct من كل دالة (method):

type Query struct {
    table   string
    columns []string
    where   string
    limit   int
}

func (q *Query) Select(cols ...string) *Query {
    q.columns = cols
    return q
}

func (q *Query) From(table string) *Query {
    q.table = table
    return q
}

func (q *Query) Where(condition string) *Query {
    q.where = condition
    return q
}

func (q *Query) Limit(n int) *Query {
    q.limit = n
    return q
}

الآن يمكنك ربط هذه الاستدعاءات بشكل انسيابي:

query := &Query{}
query.Select("name", "email").From("users").Where("active = true").Limit(10)

يُقرأ هذا تقريبًا مثل اللغة الطبيعية مقارنةً بالبيانات المنفصلة. يعمل تسلسل الأساليب (Method chaining) بشكل أفضل عندما تقوم العمليات بتهيئة أو تعديل كائن دون الحاجة إلى إرجاع قيم أخرى. ويُستخدم بشكل شائع في بناة الاستعلامات (query builders)، وواجهات برمجة تطبيقات التكوين (configuration APIs)، ومكتبات تأكيد الاختبارات (test assertion libraries).

تذكر أن كل تابع (method) يجب أن يستخدم مستقبل مؤشر (pointer receiver) ويعيد *StructType لكي تعمل السلسلة (chain) بشكل صحيح.

challenge icon

التحدي

سهل

لنقم ببناء منشئ عناصر HTML انسيابي (fluent) يستخدم تسلسل الأساليب (method chaining) لإنشاء وسوم HTML مع السمات والمحتوى! هذا تطبيق عملي لتسلسل الأساليب — ستنشئ واجهة برمجة تطبيقات (API) تُقرأ تقريبًا مثل اللغة الطبيعية عند بناء عناصر HTML.

ستقوم بتنظيم الكود الخاص بك عبر ملفين:

  • element.go: حدد منشئ عناصر HTML الخاص بك مع أساليب قابلة للتسلسل.

    قم بإنشاء هيكل Element يخزن اسم الوسم، وخريطة للسمات (سلسلة نصية إلى سلسلة نصية)، والمحتوى الداخلي. قم ببناء هذه الأساليب القابلة للتسلسل والتي يعيد كل منها *Element:

    • NewElement(tag string) - منشئ (constructor) ينشئ عنصرًا جديدًا باسم الوسم المعطى وخريطة سمات مهيأة (فارغة).
    • Attr(key, value string) - يضيف سمة إلى العنصر.
    • ID(id string) - أسلوب ملائم يضبط سمة "id".
    • Class(class string) - أسلوب ملائم يضبط سمة "class".
    • Content(text string) - يضبط المحتوى الداخلي للعنصر.

    أضف أسلوب Render() الذي يعيد سلسلة HTML النصية. يجب أن تظهر السمات بترتيب أبجدي حسب المفتاح. التنسيق هو:

    <tag attr1="value1" attr2="value2">content</tag>

    إذا لم تكن هناك سمات، فقم فقط بتقديم <tag>content</tag>. إذا لم يكن هناك محتوى، فقم بتقديم <tag attr="value"></tag>.

  • main.go: بناء عناصر HTML باستخدام تسلسل الأساليب.

    اقرأ اسم الوسم، ثم اقرأ عدد العمليات المطلوب تنفيذها. كل عملية هي واحدة مما يلي:

    • id متبوعًا بقيمة ID
    • class متبوعًا بقيمة class
    • attr متبوعًا باسم السمة وقيمتها (سطران)
    • content متبوعًا بنص المحتوى

    قم بتسلسل جميع العمليات معًا بانسيابية، ثم اطبع كود HTML الناتج.

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

  • السطر 1: اسم الوسم
  • السطر 2: عدد العمليات
  • الأسطر التالية: نوع العملية والقيمة (أو القيم)

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

div
3
id
container
class
main-content
content
Hello World

يجب أن يكون مخرجك:

<div class="main-content" id="container">Hello World</div>

وإذا كان المعطى:

a
3
attr
href
https://example.com
attr
target
_blank
content
Click here

يجب أن يكون مخرجك:

<a href="https://example.com" target="_blank">Click here</a>

وإذا كان المعطى:

input
2
attr
type
text
attr
placeholder
Enter name

يجب أن يكون مخرجك:

<input placeholder="Enter name" type="text"></input>

وإذا كان المعطى:

p
1
content
Simple paragraph

يجب أن يكون مخرجك:

<p>Simple paragraph</p>

لاحظ كيف يتيح لك تسلسل الأساليب بناء العناصر خطوة بخطوة بطريقة مقروءة. يقوم كل أسلوب بتعديل العنصر وإعادته، مما يسمح باستدعاء الأسلوب التالي بشكل متسلسل ومباشر.

ورقة مرجعية

تسلسل الدوال (Method chaining) هو تقنية تعيد فيها الدوال المستلم (عادةً *StructType)، مما يسمح بربط استدعاءات دوال متعددة معاً في عبارة برمجية واحدة.

يجب أن تستخدم كل دالة مستلم مؤشر (pointer receiver) وتعيد *StructType:

type Query struct {
    table   string
    columns []string
    where   string
    limit   int
}

func (q *Query) Select(cols ...string) *Query {
    q.columns = cols
    return q
}

func (q *Query) From(table string) *Query {
    q.table = table
    return q
}

func (q *Query) Where(condition string) *Query {
    q.where = condition
    return q
}

func (q *Query) Limit(n int) *Query {
    q.limit = n
    return q
}

استدعاء الدوال المتسلسلة بسلاسة:

query := &Query{}
query.Select("name", "email").From("users").Where("active = true").Limit(10)

يعمل تسلسل الدوال بشكل أفضل عندما تقوم العمليات بتكوين أو تعديل كائن دون الحاجة إلى إرجاع قيم أخرى. ويشيع استخدامه في بناة الاستعلامات (query builders)، وواجهات برمجة تطبيقات التكوين (configuration APIs)، ومكتبات تأكيد الاختبارات (test assertion libraries).

جرّب بنفسك

package main

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

func main() {
	scanner := bufio.NewScanner(os.Stdin)

	// قراءة اسم الوسم
	scanner.Scan()
	tagName := scanner.Text()

	// قراءة عدد العمليات
	scanner.Scan()
	numOps, _ := strconv.Atoi(scanner.Text())

	// إنشاء العنصر
	element := NewElement(tagName)

	// معالجة كل عملية
	for i := 0; i < numOps; i++ {
		scanner.Scan()
		operation := scanner.Text()

		// TODO: بناءً على نوع العملية، قم بربط الطريقة المناسبة
		// العمليات يمكن أن تكون: "id" أو "class" أو "attr" أو "content"
		// - لـ "id": اقرأ السطر التالي كقيمة للمعرف (ID)
		// - لـ "class": اقرأ السطر التالي كقيمة للفئة (class)
		// - لـ "attr": اقرأ السطرين التاليين (اسم الخاصية، ثم قيمتها)
		// - لـ "content": اقرأ السطر التالي كنص المحتوى
		// استخدم تسلسل الطرق (method chaining) لبناء العنصر بسلاسة

		_ = operation // قم بإزالة هذا السطر عند التنفيذ
	}

	// طباعة كود HTML الناتج
	fmt.Println(element.Render())
}
quiz iconاختبر نفسك

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

جميع دروس Object Oriented Programming