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

فهم الـ Closures

جزء من قسم Logic & Flow في رحلة Dart على Coddy — الدرس 46 من 65.

الـ closure هو نوع خاص من الدوال التي "تتذكر" المتغيرات من المكان الذي أُنشئت فيه، حتى بعد انتهاء تنفيذ ذلك السياق الأصلي. فكر فيها كدالة تحمل معها جزءاً من مكان نشأتها أينما ذهبت.

عندما تقوم بإنشاء دالة داخل دالة أخرى، فإن الدالة الداخلية تمتلك صلاحية الوصول إلى متغيرات الدالة الخارجية. وما يجعل هذا "closure" هو أن صلاحية الوصول هذه تستمر حتى بعد انتهاء تنفيذ الدالة الخارجية.

Function createGreeting(String name) {
  return () {
    return "Hello, $name!";
  };
}

في هذا المثال، الدالة المجهولة (anonymous function) التي يتم إرجاعها بواسطة createGreeting هي closure. فهي تلتقط المعامل name من النطاق المحيط بها. وحتى بعد انتهاء createGreeting من التنفيذ، تظل الدالة المُرجعة تتذكر ما كانت عليه قيمة name.

تعد الـ Closures مفيدة للغاية لإنشاء وظائف متخصصة أو الحفاظ على الحالة بطريقة نظيفة. فهي تتيح لك بناء وظائف مخصصة بناءً على البيئة التي تم إنشاؤها فيها، مما يجعل الكود الخاص بك أكثر مرونة وقوة.

challenge icon

التحدي

سهل

قم بإنشاء برنامج يوضح مفهوم الإغلاقات (closures) من خلال بناء نظام منشئ رسائل مخصص. سيقوم برنامجك بإنشاء دوال "تتذكر" معلومات محددة وتستخدم تلك المعلومات لإنشاء رسائل مخصصة حتى بعد انتهاء السياق الأصلي.

  1. اقرأ مدخلاً نصياً يمثل اسم الشخص
  2. اقرأ مدخلاً نصياً يمثل نوع التحية ("formal"، أو "casual"، أو "friendly")
  3. اقرأ مدخلاً نصياً يمثل اسم الشركة
  4. أنشئ دالة تسمى createMessageGenerator تأخذ الاسم ونوع التحية كمعاملات
  5. يجب أن تعيد الدالة createMessageGenerator دالة أخرى (إغلاق/closure) تقوم بما يلي:
    • تأخذ اسم الشركة كمعامل لها
    • تستخدم الاسم ونوع التحية من نطاق (scope) الدالة الخارجية
    • تعيد رسالة منسقة بناءً على نوع التحية:
      • لـ "formal": "Dear [name], we are pleased to welcome you to [company]."
      • لـ "casual": "Hey [name]! Welcome to [company]!"
      • لـ "friendly": "Hi [name], so glad you joined [company]!"
  6. استدعِ الدالة createMessageGenerator مع مدخلات الاسم ونوع التحية للحصول على دالة الإغلاق الخاصة بك
  7. استدعِ دالة الإغلاق الناتجة مع مدخل اسم الشركة لإنشاء الرسالة
  8. اعرض النتائج بالتنسيق الدقيق الموضح أدناه

على سبيل المثال، إذا كانت المدخلات هي "Alice"، و "formal"، و "TechCorp"، يجب أن يخرج برنامجك:

Message Generator System
========================
Creating message generator for: Alice
Greeting type: formal
Company: TechCorp
========================
Generated message: Dear Alice, we are pleased to welcome you to TechCorp.
Message generation completed successfully

إذا كانت المدخلات هي "Bob"، و "casual"، و "StartupXYZ"، يجب أن يخرج برنامجك:

Message Generator System
========================
Creating message generator for: Bob
Greeting type: casual
Company: StartupXYZ
========================
Generated message: Hey Bob! Welcome to StartupXYZ!
Message generation completed successfully

إذا كانت المدخلات هي "Carol"، و "friendly"، و "InnovateLab"، يجب أن يخرج برنامجك:

Message Generator System
========================
Creating message generator for: Carol
Greeting type: friendly
Company: InnovateLab
========================
Generated message: Hi Carol, so glad you joined InnovateLab!
Message generation completed successfully

يجب أن يوضح برنامجك مفهوم الإغلاقات (closures) من خلال إنشاء دالة تعيد دالة أخرى. يجب أن تتمتع الدالة المعادة (الإغلاق) بإمكانية الوصول إلى المتغيرات من نطاق الدالة الخارجية (الاسم ونوع التحية) حتى بعد انتهاء تنفيذ الدالة الخارجية. استخدم الجمل الشرطية لتحديد تنسيق الرسالة المناسب بناءً على مدخل نوع التحية.

ورقة مرجعية

الـ closure هي دالة "تتذكر" المتغيرات من المكان الذي أُنشئت فيه، حتى بعد انتهاء تشغيل السياق الأصلي.

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

Function createGreeting(String name) {
  return () {
    return "Hello, $name!";
  };
}

في هذا المثال، الدالة المجهولة التي تعيدها createGreeting هي closure. فهي تلتقط المعامل name من النطاق المحيط بها. وحتى بعد انتهاء تشغيل createGreeting، تظل الدالة المعادة تتذكر قيمة name.

تعد الـ closures مفيدة لإنشاء دوال متخصصة أو الحفاظ على الحالة بطريقة نظيفة. فهي تسمح لك ببناء دوال مخصصة بناءً على البيئة التي أُنشئت فيها.

جرّب بنفسك

import 'dart:io';

void main() {
  // قراءة المدخلات
  String? name = stdin.readLineSync();
  String? greetingType = stdin.readLineSync();
  String? company = stdin.readLineSync();
  
  // عرض ترويسة النظام
  print("Message Generator System");
  print("========================");
  print("Creating message generator for: $name");
  print("Greeting type: $greetingType");
  print("Company: $company");
  print("========================");
  
  // TODO: اكتب الكود الخاص بك أدناه
  // إنشاء دالة createMessageGenerator التي تعيد closure
  // استدعاء الدالة وتوليد الرسالة
  
  // إخراج النتائج النهائية
  print("Generated message: \$message");
  print("Message generation completed successfully");
}
quiz iconاختبر نفسك

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

جميع دروس Logic & Flow