تنفيذ الـ Interfaces
جزء من قسم Object Oriented Programming في رحلة C على Coddy — الدرس 41 من 61.
الآن بعد أن فهمت ماهية الـ interface — وهي عبارة عن struct يحتوي فقط على function pointers — فقد حان الوقت لإنشاء concrete implementations تفي بهذا الـ contract.
تذكر واجهة ILogger الخاصة بنا من الدرس السابق:
typedef void (*LogFunc)(const char* message);
typedef struct {
LogFunc log;
} ILogger;لتنفيذ هذه الواجهة، نكتب دوالاً فعلية تطابق توقيع LogFunc، ثم ننشئ مثيلات ILogger مع تعيين تلك الدوال لها:
void console_log(const char* message) {
printf("[CONSOLE] %s\n", message);
}
void file_log(const char* message) {
printf("[FILE] %s\n", message); // محاكاة مخرجات الملف
}
ILogger create_console_logger() {
ILogger logger = { console_log };
return logger;
}
ILogger create_file_logger() {
ILogger logger = { file_log };
return logger;
}تعيد كل دالة "constructor" كائن ILogger مع دالة مختلفة مرتبطة بها. لا يحتاج الكود الذي يستخدم أدوات التسجيل (loggers) هذه إلى معرفة أي تنفيذ (implementation) تلقاه:
void do_work(ILogger* logger) {
logger->log("Starting work...");
logger->log("Work complete!");
}
int main() {
ILogger console = create_console_logger();
ILogger file = create_file_logger();
do_work(&console); // يستخدم console_log
do_work(&file); // يستخدم file_log
return 0;
}إن الدالة do_work منفصلة تماماً عن آلية التسجيل (logging). يمكنك تبديل أدوات التسجيل بحرية دون تغيير أي من المنطق الأساسي — هذه هي قوة البرمجة وفقاً لواجهة (interface).
التحدي
سهلدعنا نبني نظام INotifier يوضح كيف يمكن للتطبيقات المختلفة أن تفي بنفس عقد الواجهة (interface contract). ستقوم بإنشاء أدوات إشعار ملموسة — EmailNotifier و SMSNotifier — كلاهما يتوافق مع واجهة مشتركة ولكنهما ينتجان مخرجات مختلفة.
ستقوم بتنظيم الكود الخاص بك عبر ثلاثة ملفات:
notifier.h: حدد الواجهة هنا. أنشئ نوع مؤشر دالة يسمىNotifyFuncيأخذ رسالةconst char*ولا يعيد شيئاً. ثم حدد هيكلINotifierيحتوي فقط على مؤشر دالةnotifyمن هذا النوع. أعلن أيضاً عن دالتي بناء (constructor functions):create_email_notifierوcreate_sms_notifier، كل منهما تعيدINotifierبالقيمة.notifier.c: قم بتنفيذ دوال الإشعار الملموسة ودوال البناء هنا. أنشئ:email_notify— يطبع الرسالة بالتنسيق:[EMAIL] messagesms_notify— يطبع الرسالة بالتنسيق:[SMS] messagecreate_email_notifier— يعيدINotifierمرتبطاً بـemail_notifycreate_sms_notifier— يعيدINotifierمرتبطاً بـsms_notify
main.c: اجمع كل شيء معاً هنا. اقرأ نوع الإشعار والرسالة، وأنشئ أداة الإشعار المناسبة باستخدام دوال البناء، وأرسل الإشعار من خلال الواجهة.
سيتلقى برنامجك مدخلين: نوع الإشعار (1 للبريد الإلكتروني، 2 للرسائل القصيرة SMS) و رسالة لإرسالها.
استخدم دوال البناء لإنشاء أداة الإشعار المناسبة، ثم استدعِ notify من خلال الواجهة لعرض الرسالة.
مثال للمخرجات عندما يكون النوع 1 والرسالة Meeting at 3pm:
[EMAIL] Meeting at 3pmمثال للمخرجات عندما يكون النوع 2 والرسالة Your code shipped:
[SMS] Your code shippedتكمن قوة هذا النمط في أن main.c لا يحتاج إلى معرفة كيفية عمل كل أداة إشعار داخلياً — فهو ببساطة يستدعي دالة notify الخاصة بالواجهة، ويتم تنفيذ التطبيق الصحيح. تذكر استخدام حراس التضمين (include guards) في ملف الرأس الخاص بك.
جرّب بنفسك
#include <stdio.h>
#include "notifier.h"
int main() {
int type;
char message[256];
// قراءة نوع الإشعار (1 للبريد الإلكتروني، 2 للرسائل القصيرة SMS)
scanf("%d", &type);
getchar(); // استهلاك السطر الجديد
// قراءة الرسالة
fgets(message, sizeof(message), stdin);
// إزالة السطر الجديد في النهاية إذا وجد
int len = 0;
while (message[len] != '\0') len++;
if (len > 0 && message[len-1] == '\n') message[len-1] = '\0';
// TODO: إنشاء المُخطر (notifier) المناسب بناءً على النوع
// استخدم create_email_notifier() للنوع 1
// استخدم create_sms_notifier() للنوع 2
// TODO: استدعاء دالة notify من خلال الواجهة
// notifier.notify(message);
return 0;
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس Object Oriented Programming
1أساسيات البرمجة التركيبية
ملفات الترويسةحواجز التضمينملفات المصدرالدوال الساكنةمراجعة: آلة حاسبة تركيبية4التغليف (Encapsulation)
مفهوم الـ Opaque Pointersتعريف الـ Opaque Structsالـ Getters والـ Settersالتحقق من البيانات في الـ Settersملخص: الصندوق السري2الكائنات والأساليب
الـ Structs ككائناتمؤشر 'Self'صحة استخدام Constالمؤشر مقابل القيمةالأساليب المساعدةملخص: Point Manager5مشروع: حساب بنكي بسيط
إعداد المشروعتنفيذ الحساب8تعدد الأشكال (Polymorphism)
مؤشرات الدوال في الـ Structsمحاكاة الـ Methodsمفهوم الـ Interfaceتنفيذ الـ Interfacesالتكرار متعدد الأشكالمراجعة: Greeter3دورة حياة الكائن
نمط المنشئ (Constructor Pattern)نمط الهادم (Destructor Pattern)تهيئة الـ Stackالنسخ العميق (Deep Copy)مراجعة: String Wrapper6الوراثة عبر التركيب
تضمين الـ Structقاعدة العضو الأولالوصول إلى أعضاء الأبعملية الـ Upcastingمراجعة: هرمية الأشكال9مشروع: رسّام الأشكال
نظرة عامة على المشروعتنفيذ الدائرةتنفيذ المستطيلاستخدام تعدد الأشكالحاوية الأشكال