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

محاكاة الـ Methods

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

لقد رأيت كيف تضع مؤشّر function داخل بنية. تظهر القوة الحقيقية عندما تعيّن دوالًا مختلفة إلى instances مختلفة من نوع البنية نفسه. هكذا نحاكي methods ذات سلوك متباين.

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

typedef void (*ActionFunc)(void);

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

عند إنشاء instances، تقوم بربط functions مختلفة بكل واحدة منها:

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 عبر الإنترنت