الإستخدام العملي للإنترفيس في Csharp
- ما هو الإنترفيس
- فوائد الإنترفيس
- مثال عملي الإنترفيس
ما هو الإنترفيس
في البرمجة الكائنية ( OOP ) يعتبر الإنترفيس ( Interface ) من الوسائل الأساسية لتنظيم الكود بطريقة نظيفة و مرنة فهي أشبه بعقد أو اتفاق يُحدد ما يجب أن يفعله الكلاس، و لكن دون أن يحدد كيف سيتم ذلك.
الإنترفيس يعرّف التوقيع ( Signature ) الخاص بالدوال – أي أسماءها، و أنواع مدخلاتها و مخرجاتها – دون أن يحتوي على أي منطق داخلي أو تفاصيل تنفيذية و في المقابل، الكلاس الذي يطبق ( Implements ) هذا الإنترفيس، يكون ملزما بتنفيذ كل الدوال الموجودة فيها.
فوائد الإنترفيس
فيما يلي أهم الاستخدامات العملية للإنترفيس:
- فصل التعريف ( Interface Definition ) عن التنفيذ ( Implementation ) الكود الذي يتعامل مع الواجهة لا يهتم بكيفية تنفيذ الدوال، بل يركز فقط على أنها موجودة ويمكن استدعاؤها.
- تحسين قابلية الاختبار ( Testability ) أثناء الاختبارات، يمكن استخدام كائنات وهمية ( Mocks ) تنفذ نفس الواجهة، دون الاعتماد على الكائنات الفعلية.
- تطبيق مبدأ الانعكاسية ( Dependency Inversion Principle ) حيث يعتمد الكود على التجريد ( Abstraction ) بدلاً من الاعتماد المباشر على كائنات حقيقية، مما يجعل الكود أقل ترابطاً و أسهل للتعديل.
- يسماح بالتبديل بين أكثر من تنفيذ ( Implementation Switching ) من أبرز فوائد استخدام الإنترفيس أنه يتيح بالتبديل بين أكثر من تنفيذ. أي أنك تستطيع تغيير الكلاس الذي ينفذ الإنترفيس في أي وقت، دون الحاجة لتعديل الكود الذي يعتمد عليها، طالما أن هذا الكود يتعامل مع الإنترفيس و ليس مع تنفيذه المباشر.
مثال عملي الإنترفيس
لنفترض أننا قمنا بإنشاء إنترفيس لإدارة الرسائل إسمه IMessageService
و يحتوي على دالة إسمها Send()
.
هذا الإنترفيس يمكننا تنفيذه في كلاس مثل EmailService
لإرسال الرسائل عبر البريد الإلكتروني. و إذا أردنا لاحقاً التبديل إلى إرسال الرسائل عبر الهاتف فكل ما علينا هو إنشاء كلاس جديد مثل SmsService
يطبق نفس الإنترفيس.
الكود الذي يعتمد على الإنترفيس IMessageService
مثلاً كلاس إسمه NotificationManager
لن يحتاج لأي تعديل لأنه لا يهتم بطريقة التنفيذ الخاصة بهذا الإنترفيس، بل فقط يعرف أنه يوجد فيه الدالة Send()
و التي تقوم بإرسال رسائل (لا يهمه إن كان عبر البريد الإلكتروني أو الهاتف).
هكذا يصبح بإمكاننا تمرير أي كائن نريده من الخارج — سواء كان من EmailService
أو من SmsService
أو حتى من MockService
للاختبارات — دون المساس ببنية النظام.
هذه المرونة تجعل الكود قابلاً للتوسع، أسهل للاختبار، و أسهل للتعديل مستقبلاً.
الآن، لنفترض أنه لدينا إنترفيس لإرسال الرسائل كما يلي.
مثال
public interface IMessageService { void Send(string message); }
بعدها قمنا بإنشاء كلاس ينفذه بهدف إرسال رسائل عبر البريد الإلكتروني كما يلي.
مثال
public class EmailService : IMessageService { public void Send(string message) { Console.WriteLine($"Sending Email: {message}"); } }
و في وقت لاحق، قررنا إرسال رسائل عبر SMS عبر الهاتف بدلاً من البريد الإلكتروني، فأضفنا كلاس جديد ينفذ الإنترفيس كما يلي.
مثال
public class SmsService : IMessageService { public void Send(string message) { Console.WriteLine($"Sending SMS: {message}"); } }
نلاحظ أن الكلاس EmailService
و الكلاس SmsService
يطبّقان نفس الإنترفيس IMessageService
و لكن كل واحد يطبقه بطريقة مختلفة.
الآن، في مكان آخر من المشروع، لدينا كلاس يعتمد على إسم الإنترفيس فقط كما يلي.
مثال
public class NotificationManager { private readonly IMessageService _messageService; public NotificationManager(IMessageService messageService) { _messageService = messageService; } public void Notify(string text) { _messageService.Send(text); } }
لاحظ أنّ NotificationManager
لا يعرف ما إذا كانت الرسالة سترسل عبر البريد أو الرسائل النصية، فهو يتعامل فقط مع إنترفيس و نحن من يقرر نوع الخدمة أثناء عملية التنفيذ كما يلي.
مثال
var emailService = new EmailService(); var smsService = new SmsService(); // هنا قمنا بإرسال رسالة عبر الإيميل var notifier = new NotificationManager(emailService); notifier.Notify("Hello via Email!"); // هنا قمنا بإرسال رسالة عبر الهاتف notifier = new NotificationManager(smsService); notifier.Notify("Hello via SMS!");