Menu
CoddyTech

محاكاة الـ Methods

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

لقد رأيت كيف تضع مؤشر دالة داخل بنية. تظهر القوة الحقيقية عندما تُسنِد دوالًا مختلفة إلى مثيلات مختلفة من نوع البنية نفسه. بهذه الطريقة نحاكي الأساليب ذات السلوك المتنوع.

تأمّل بنيةً تمثّل إجراءً بمنطق قابل للتخصيص:

typedef void (*ActionFunc)(void);

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

عند إنشاء النسخ، اربط كل نسخة بدالة مختلفة:

void say_hello(void) {
    printf("Hello!\n");
}

void say_goodbye(void) {
    printf("Goodbye!\n");
}

int main() {
    Action greet = { "Greet", say_hello };
    Action farewell = { "Farewell", say_goodbye };
    
    greet.execute();    // المخرجات: Hello!
    farewell.execute(); // المخرجات: Goodbye!
    return 0;
}

كلٌّ من greet وfarewell من النوع نفسه (Action)، ومع ذلك فإن استدعاء execute على كلٍّ منهما يؤدي إلى نتائج مختلفة تمامًا. لا تحتفظ البنية بالبيانات فحسب، بل تحتفظ أيضًا بسلوك يختلف باختلاف المثيل.

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

challenge icon

التحدي

سهل

لنبنِ نظام Speaker يوضّح كيف يمكن لنسخ مختلفة من النوع نفسه للبنية أن تُظهر سلوكيات مختلفة تمامًا، بناءً على الدالة الموصولة بها.

ستنشئ ملفين لتنظيم التعليمات البرمجية:

  • speaker.h: عرّف نوع مؤشر دالة باسم SpeakFunc لا يأخذ أي معاملات ولا يعيد أي قيمة. ثم عرّف بنية Speaker تحتوي على name (وهو const char*) ومؤشر دالة speak من النوع SpeakFunc.
  • main.c: أدرج ملف الترويسة ونفّذ ثلاث دوال مختلفة لإصدار الأصوات:
    • bark: تطبع Woof!
    • meow: تطبع Meow!
    • chirp: تطبع Chirp!
    ثم أنشئ نسختين من Speaker، وصِل كلًّا منهما بدالة مختلفة بناءً على الإدخال، واستدعِ طريقتي speak فيهما لرؤية تعدد الأشكال أثناء العمل.

سيستقبل برنامجك مدخلين: نوع المتحدث الأول (1 لـ bark، و2 لـ meow، و3 لـ chirp) ونوع المتحدث الثاني (أيضًا 1 أو 2 أو 3).

أنشئ نسختين من Speaker. يمكنك تسميتهما كما تشاء (مثل "Dog" أو "Cat" أو "Bird"، أو ببساطة "Speaker1" و"Speaker2"). صِل كل نسخة بالدالة المناسبة وفقًا لرمز الإدخال الخاص بها، ثم استدعِ speak لكل نسخة بالترتيب.

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

Woof!
Meow!

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

Chirp!
Chirp!

الفكرة الأساسية هنا هي أن كلا المتحدثين من النوع نفسه Speaker، ومع ذلك ينتجان مخرجات مختلفة لأن لكل منهما دالة مختلفة معيّنة لعضو speak. تذكّر استخدام حواجز التضمين في ملف الترويسة.

جرّب بنفسك

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

// TODO: نفّذ الدالة bark التي تطبع "Woof!"

// TODO: نفّذ الدالة meow التي تطبع "Meow!"

// TODO: نفّذ الدالة chirp التي تطبع "Chirp!"

int main() {
    int type1, type2;
    scanf("%d", &type1);
    scanf("%d", &type2);
    
    // TODO: أنشئ مثيلين من Speaker
    
    // TODO: اربط الدالة speak للمتحدث الأول بناءً على type1
    // (1 = bark، 2 = meow، 3 = chirp)
    
    // TODO: اربط الدالة speak للمتحدث الثاني بناءً على type2
    // (1 = bark، 2 = meow، 3 = chirp)
    
    // TODO: استدعِ speak لكل متحدث بالترتيب
    
    return 0;
}
quiz iconاختبر نفسك

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

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

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