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

التكرار متعدد الأشكال

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

لقد تعلّمت إنشاء الواجهات وImplementها باستخدام functions ملموسة مختلفة. وتظهر الفائدة الحقيقية عندما تتمكّن من التعامل مع مجموعة من الكائنات المختلفة بشكل موحّد: Iterate خلالها واستدعاء pointer function نفسه على كلٍّ منها، بغضّ النظر عن السلوك المحدّد المرتبط بها.

تخيّل أن لديك مصفوفة من هياكل Action، لكلٍّ منها دالة execute مُسنَدة إليها:

typedef void (*ExecuteFunc)(void);

typedef struct {
    const char* name;
    ExecuteFunc execute;
} Action;

void jump(void) { printf("Jumping!\n"); }
void run(void)  { printf("Running!\n"); }
void rest(void) { printf("Resting...\n"); }

يمكنك إنشاء مصفوفة من هذه الإجراءات، بحيث يرتبط كل منها بدالة مختلفة، ثم التكرار عبرها باستخدام حلقة for بسيطة:

int main() {
    Action actions[3] = {
        { "Jump", jump },
        { "Run", run },
        { "Rest", rest }
    };
    
    for (int i = 0; i < 3; i++) {
        printf("%s: ", actions[i].name);
        actions[i].execute();
    }
    return 0;
}

لا تعرف الحلقة ولا تهتم بما يفعله كل Action داخليًا. إنها تستدعي ببساطة execute() على كل عنصر.

هذا هو تعدد الأشكال قيد التنفيذ: يتعامل الكود نفسه مع كائنات ذات سلوكيات مختلفة تمامًا. لا يتطلب إضافة نوع إجراء جديد أي تغييرات في منطق التكرار؛ ما عليك سوى إضافة عنصر آخر إلى array.

challenge icon

التحدي

سهل

لنبنِ نظامًا لإدارة Task يوضّح التكرار متعدد الأشكال: معالجة مجموعة من الكائنات التي تشترك في واجهة common، لكنها تنفّذ سلوكيات مختلفة.

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

  • task.h: Define واجهة المهمة هنا. Create نوع مؤشر function يُسمّى TaskFunc، ولا يأخذ parameters ويُرجع nothing. ثم Define بنية Task containing name (وهو const char*) ومؤشر function ‏run من النوع TaskFunc.
  • task.c: Implement ثلاث functions مختلفة للمهام، تمثّل أنواعًا مختلفة من العمل:
    • backup_task: تطبع Backing up data...
    • cleanup_task: تطبع Cleaning up files...
    • report_task: تطبع Generating report...
  • main.c: اجمع كل شيء هنا. Create array من بنيات Task، تكون كل واحدة منها مرتبطة بـ function مهمة مختلفة. ثم Iterate عبر array وexecute كل مهمة polymorphically؛ وبالنسبة إلى كل مهمة، اطبع اسمها ثم استدعِ function ‏run الخاصة بها.

سيتلقى برنامجك إدخالًا واحدًا: عدد المهام المطلوب تشغيلها (1 أو 2 أو 3).

Create array containing ثلاث مهام بالضبط بهذا order: مهمة نسخ احتياطي تُسمّى Backup، ومهمة تنظيف تُسمّى Cleanup، ومهمة تقرير تُسمّى Report. بناءً على count المُدخل، Iterate عبر هذا العدد فقط من المهام بدءًا من بداية array.

لكل مهمة في عملية التكرار، اطبع اسم المهمة متبوعًا بنقطتين ومسافة، ثم استدعِ function ‏run الخاصة بها.

مثال على الناتج عندما يكون الإدخال 2:

Backup: Backing up data...
Cleanup: Cleaning up files...

مثال على الناتج عندما يكون الإدخال 3:

Backup: Backing up data...
Cleanup: Cleaning up files...
Report: Generating report...

الفكرة الأساسية هي أن الحلقة لا تحتاج إلى معرفة ما تفعله كل مهمة. فهي تطبع الاسم ببساطة وتستدعي run() على كل عنصر. تتعامل شِفرة التكرار نفسها مع جميع أنواع المهام بشكل موحّد. تذكّر استخدام include guards في ملف الترويسة الخاص بك.

جرّب بنفسك

#include <stdio.h>
#include "task.h"

// صرّح عن دوال المهام المنفَّذة في task.c
void backup_task(void);
void cleanup_task(void);
void report_task(void);

int main() {
    int count;
    scanf("%d", &count);
    
    // TODO: أنشئ مصفوفة من 3 هياكل Task بهذا الترتيب:
    // 1. مهمة النسخ الاحتياطي المسماة "Backup" باستخدام backup_task
    // 2. مهمة التنظيف المسماة "Cleanup" باستخدام cleanup_task
    // 3. مهمة التقرير المسماة "Report" باستخدام report_task
    
    // TODO: كرّر عبر 'count' مهام من المصفوفة
    // لكل مهمة، اطبع: "<name>: " ثم استدعِ دالة run الخاصة بها
    
    return 0;
}
quiz iconاختبر نفسك

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

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

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