الواجهة مقابل الفئة المجردة (Abstract Class)
جزء من قسم Object Oriented Programming في رحلة C# على Coddy — الدرس 26 من 70.
تسمح لك كل من الواجهات (interfaces) والأصناف المجردة (abstract classes) بتعريف عقود يجب على الأصناف الأخرى اتباعها، لكنهما يخدمان أغراضاً مختلفة ولهما قدرات متميزة.
تحدد الـ واجهة (interface) ما يجب على الفئة (class) القيام به، دون أي تنفيذ (implementation). إنها بمثابة عقد صريح:
public interface IFlyable
{
void Fly();
}
public class Bird : IFlyable
{
public void Fly()
{
Console.WriteLine("Flapping wings");
}
}يمكن لـ الفئة المجردة (abstract class) أن توفر كلاً من عقد وتنفيذ مشترك. إنها بمثابة مخطط جزئي:
public abstract class Vehicle
{
public string Brand { get; set; }
public void StartEngine()
{
Console.WriteLine("Engine started");
}
public abstract void Drive(); // يجب تنفيذها
}
public class Car : Vehicle
{
public override void Drive()
{
Console.WriteLine("Driving on roads");
}
}تكمن الاختلافات الرئيسية في قواعد الوراثة والغرض.
يمكن للفئة تنفيذ واجهات متعددة ولكن يمكنها الوراثة من فئة مجردة واحدة فقط.
استخدم الواجهة (interface) عندما تحتاج فئات (classes) غير مرتبطة إلى مشاركة سلوك معين (مثل IFlyable للطيور والطائرات). استخدم فئة مجردة (abstract class) عندما تشترك فئات مرتبطة في كود وحالة مشتركة (مثل المركبات التي تشترك في آلية تشغيل المحرك).
يمكن للأصناف من نوع Abstract classes أن تحتوي على constructors، و fields، و access modifiers على الأعضاء. بينما لم تكن الـ Interfaces تسمح بذلك تقليدياً، على الرغم من أن لغة C# الحديثة تسمح بـ default implementations.
عند الشك، فضّل استخدام الواجهات (interfaces) من أجل المرونة - يمكنك دائمًا إضافة فئة مجردة (abstract class) لاحقًا إذا أصبح التنفيذ المشترك ضروريًا.
التحدي
سهللنقم ببناء نظام مشغل وسائط يوضح متى يتم استخدام الواجهات (interfaces) مقابل الفئات المجردة (abstract classes). ستقوم بإنشاء تصميم حيث تشترك الأجهزة غير المرتبطة في سلوك التشغيل من خلال واجهة، بينما تشترك أنواع الوسائط المرتبطة في تنفيذ مشترك من خلال فئة مجردة.
ستقوم بتنظيم الكود الخاص بك عبر أربعة ملفات:
IPlayable.cs: قم بتعريف واجهة تسمىIPlayableداخل مساحة الاسمMedia. تمثل هذه الواجهة العقد لأي شيء يمكنه تشغيل الوسائط - سواء كان هاتفاً، أو تلفازاً، أو مشغل موسيقى مخصصاً. يجب أن تصرح عن ميثود واحدةPlay()تعيد سلسلة نصية (string).MediaFile.cs: قم بتعريف فئة مجردة تسمىMediaFileداخل مساحة الاسمMedia. يمثل هذا الأساس المشترك لجميع ملفات الوسائط. يجب أن تحتوي على خاصيةTitle(string) وخاصيةDuration(int، تمثل الثواني). قم بتضمين منشئ (constructor) يضبط كلتا القيمتين. أضف ميثود ملموسة تسمىGetInfo()تعيد"{Title} ({Duration}s)". قم أيضاً بالتصريح عن ميثود مجردةGetType()تعيد سلسلة نصية - حيث سيحدد كل نوع وسائط نوع الملف الخاص به.AudioFile.cs: قم بتعريف فئةAudioFileداخل مساحة الاسمMediaترث منMediaFileوتنفذIPlayable. أضف خاصيةArtist(string). يجب أن يقبل المنشئ العنوان، والمدة، والفنان. قم بعمل override للميثودGetType()لتعيد"Audio". قم بتنفيذPlay()لتعيد"Playing audio: {Title} by {Artist}".Program.cs: في ملفك الرئيسي، قم بإنشاءAudioFileباستخدام قيم الإدخال. استعرض كلا جانبي الفئة: استدعِGetInfo()وGetType()(الموروثتين من الفئة المجردة)، ثم استدعِPlay()(من الواجهة). قم بتخزين ملف الصوت في متغير من نوعIPlayableواستدعِPlay()مرة أخرى لإظهار تعدد الأشكال للواجهة (interface polymorphism).
ستتلقى ثلاثة مدخلات:
- عنوان الأغنية
- المدة بالثواني
- اسم الفنان
اطبع المخرجات بهذا التنسيق:
Info: {GetInfo() result}
Type: {GetType() result}
Direct: {Play() result}
Via Interface: {Play() result from IPlayable variable}على سبيل المثال، إذا كانت المدخلات هي Bohemian Rhapsody، و 354، و Queen، يجب أن تكون المخرجات:
Info: Bohemian Rhapsody (354s)
Type: Audio
Direct: Playing audio: Bohemian Rhapsody by Queen
Via Interface: Playing audio: Bohemian Rhapsody by Queenلاحظ كيف تستفيد AudioFile من كلا النهجين: فهي ترث التنفيذ المشترك (GetInfo()) من الفئة المجردة بينما تلتزم أيضاً بعقد IPlayable. توفر الفئة المجردة إعادة استخدام الكود لأنواع الوسائط المرتبطة، بينما تسمح الواجهة لأي فئة غير مرتبطة بأن تكون "قابلة للتشغيل" دون مشاركة تسلسل هرمي للوراثة.
ورقة مرجعية
تُعرف الواجهة (interface) عقداً يجب على الفئات اتباعه، دون أي تنفيذ:
public interface IFlyable
{
void Fly();
}
public class Bird : IFlyable
{
public void Fly()
{
Console.WriteLine("Flapping wings");
}
}توفر الفئة المجردة (abstract class) كلاً من العقد والتنفيذ المشترك:
public abstract class Vehicle
{
public string Brand { get; set; }
public void StartEngine()
{
Console.WriteLine("Engine started");
}
public abstract void Drive(); // Must be implemented
}
public class Car : Vehicle
{
public override void Drive()
{
Console.WriteLine("Driving on roads");
}
}الاختلافات الرئيسية:
- يمكن للفئة تنفيذ واجهات متعددة ولكن يمكنها الوراثة من فئة مجردة واحدة فقط
- استخدم الواجهات عندما تحتاج فئات غير مرتبطة إلى مشاركة سلوك معين
- استخدم الفئات المجردة عندما تشترك الفئات المرتبطة في كود وحالة مشتركة
- يمكن أن تحتوي الفئات المجردة على مشيدات، وحقول، ومحددات وصول
- يفضل استخدام الواجهات من أجل المرونة
جرّب بنفسك
using System;
using Media;
class Program
{
public static void Main(string[] args)
{
// قراءة قيم المدخلات
string title = Console.ReadLine();
int duration = Convert.ToInt32(Console.ReadLine());
string artist = Console.ReadLine();
// TODO: إنشاء AudioFile باستخدام قيم المدخلات
// TODO: طباعة Info: متبوعة بنتيجة GetInfo()
// TODO: طباعة Type: متبوعة بنتيجة GetType()
// TODO: طباعة Direct: متبوعة بنتيجة Play()
// TODO: تخزين ملف الصوت في متغير IPlayable
// TODO: طباعة Via Interface: متبوعة بنتيجة Play() من متغير IPlayable
}
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس Object Oriented Programming
1أساسيات OOP
الملفات الخارجيةNamespaces والتوجيهاتمقدمة في Classes و Objectsالكلمة المفتاحية 'this'Methods والمعاملاتFields مقابل PropertiesConstructorsObject Initializersمراجعة - آلة حاسبة بسيطة4الوراثة
صيغة الوراثة الأساسية (:)الكلمة المفتاحية 'base'الكلمات المفتاحية Virtual و Overrideالأصناف المختومة (Sealed Classes)الفئة الأساسية 'object'مراجعة - هيكلية الموظفين7ميزات متقدمة
تحميل العوامل (Operator Overloading)المفهرسات (Indexers (this[]))إعادة تعريف ()ToStringدوال التوسعة (Extension Methods)ملخص - Custom List2الخصائص والأعضاء الساكنة (Static Members)
الخصائص المطبقة تلقائيًا (Auto-Implemented Properties)خصائص القراءة فقط والكتابة فقطالحقول والدوال الساكنة (Static)الفئات الساكنة (Static Classes)الأعضاء ذات البنية التعبيرية (Expression-Bodied Members)5تعدد الأشكال والواجهات (Polymorphism & Interfaces)
تعدد الأشكال: وقت التجميع مقابل وقت التشغيلالواجهة مقابل الفئة المجردة (Abstract Class)الواجهات المتعددةالواجهات الصريحةUpcasting و Downcastingملخص - حاسبة الأشكال8مفاهيم البرمجة كائنية التوجه (OOP) المتقدمة
التركيب بدلاً من الوراثةالـ Generics (الأصناف والدوال)الـ Delegates والأحداثالـ Attributes والـ Reflectionواجهة IDisposable وجملة usingأساسيات Dependency Injection