تطبيق البرمجة كائنية التوجه في لغة سي شارب C# – الجزء الثاني
تُعدّ البرمجة كائنية التوجه (Object-Oriented Programming – OOP) من أبرز الأنماط البرمجية التي أحدثت تحولاً جذرياً في طريقة بناء وتصميم البرمجيات الحديثة، حيث تعتمد على مفاهيم مثل الكائنات (Objects) والفئات (Classes) والتوريث (Inheritance) والتعددية (Polymorphism) والتغليف (Encapsulation). وفي لغة سي شارب #C، تم تبنّي هذا النموذج بشكل متكامل، مما يجعلها إحدى اللغات الرائدة في بيئة تطوير البرمجيات باستخدام OOP، ويدعمها إطار عمل .NET بشكل فعّال.
في الجزء الأول من هذا الموضوع، تم التعرف على المبادئ الأساسية للبرمجة كائنية التوجه في #C، مثل تعريف الكائنات، الفئات، الخصائص، والطرق. أما في هذا الجزء الثاني، سيتم التعمق أكثر في المفاهيم المتقدمة، ودراسة كيفية تطبيق تلك المبادئ في مشاريع حقيقية باستخدام #C ضمن إطار العمل .NET، مع التركيز على التوريث، التعددية، الواجهات (Interfaces)، الأصناف المجردة (Abstract Classes)، والمبادئ التصميمية المرتبطة بها.
التوريث (Inheritance)
مفهوم التوريث
يُعد التوريث أحد الركائز الأساسية في OOP، ويُتيح إنشاء فئة جديدة (الفرعية – Derived Class) من فئة موجودة مسبقًا (الأساسية – Base Class)، بحيث ترث هذه الفئة الجديدة خصائص وطرق الفئة الأصلية، مع إمكانية إضافة أو تعديل الوظائف حسب الحاجة.
التوريث في لغة #C
في #C، يتم تطبيق التوريث باستخدام الكلمة المفتاحية : بعد اسم الفئة الجديدة، يليها اسم الفئة الأساسية. تدعم #C التوريث الأحادي فقط، أي أن كل فئة يمكن أن ترث من فئة واحدة فقط، ولكن يمكن تجاوز هذا القيد باستخدام الواجهات.
csharppublic class Person
{
public string Name { get; set; }
public void Speak()
{
Console.WriteLine("Speaking...");
}
}
public class Student : Person
{
public string StudentID { get; set; }
public void Study()
{
Console.WriteLine("Studying...");
}
}
في هذا المثال، فئة Student ترث من فئة Person، وبالتالي يمكنها الوصول إلى الخصائص والوظائف الخاصة بها مثل Name وSpeak().
استخدام base
توفر الكلمة المفتاحية base طريقة للوصول إلى أعضاء الفئة الأساسية من الفئة الفرعية، خاصة في حال وجود تداخل في الوظائف أو الرغبة في توسيع السلوك الأصلي.
csharppublic class Employee : Person
{
public string JobTitle { get; set; }
public new void Speak()
{
base.Speak();
Console.WriteLine("And I'm working.");
}
}
التعددية (Polymorphism)
مفهوم التعددية
تشير التعددية إلى قدرة الكائن على أخذ أشكال متعددة، وهي ميزة تتيح استبدال كائنات الفئة الأساسية بكائنات من فئات فرعية دون التأثير على الشيفرة البرمجية. تُستخدم التعددية بشكل رئيسي لتنفيذ “التصميم العام” القابل للتوسعة.
التعددية عبر إعادة التعريف (Overriding)
في لغة #C، يمكن استخدام الكلمة المفتاحية virtual في الفئة الأساسية لتحديد إمكانية إعادة تعريف طريقة معينة، بينما يتم استخدام override في الفئة الفرعية لإعادة تعريفها.
csharppublic class Animal
{
public virtual void MakeSound()
{
Console.WriteLine("Generic animal sound");
}
}
public class Dog : Animal
{
public override void MakeSound()
{
Console.WriteLine("Bark");
}
}
التعددية في التشغيل (Runtime Polymorphism)
يمكننا استخدام مؤشرات (References) من الفئة الأساسية لتخزين كائنات من الفئة الفرعية.
csharpAnimal myAnimal = new Dog();
myAnimal.MakeSound(); // ستطبع "Bark" بفضل التعددية
التغليف (Encapsulation)
المفهوم العام
يعني التغليف إخفاء التفاصيل الداخلية للبيانات وتنظيم الوصول إليها من خلال واجهة خارجية محددة. يُسهم ذلك في حماية البيانات من التلاعب غير المرغوب فيه ويجعل النظام أكثر أمانًا وسهولة في الصيانة.
تحقيق التغليف في #C
يتم تحقيق التغليف عبر مستويات الوصول (Access Modifiers)، مثل private وprotected وpublic.
csharppublic class BankAccount
{
private decimal balance;
public void Deposit(decimal amount)
{
if (amount > 0)
balance += amount;
}
public decimal GetBalance()
{
return balance;
}
}
الفئات المجردة (Abstract Classes)
تعريف الفئة المجردة
الفئة المجردة هي فئة لا يمكن إنشاء كائنات منها مباشرة، وتُستخدم كقالب لفئات أخرى. يمكن أن تحتوي على طرق مجردة (لا تحتوي على تنفيذ) وأخرى غير مجردة.
csharppublic abstract class Shape
{
public abstract double GetArea();
public void Display()
{
Console.WriteLine("Displaying shape");
}
}
public class Circle : Shape
{
public double Radius { get; set; }
public override double GetArea()
{
return Math.PI * Radius * Radius;
}
}
الواجهات (Interfaces)
تعريف الواجهات
الواجهة هي نوع خاص يُحدد مجموعة من التواقيع للوظائف التي يجب على الفئات التي تطبقه تنفيذها. بعكس الفئات المجردة، لا تحتوي الواجهات على أي تنفيذ.
csharppublic interface IDriveable
{
void Start();
void Stop();
}
public class Car : IDriveable
{
public void Start() => Console.WriteLine("Car started");
public void Stop() => Console.WriteLine("Car stopped");
}
أهمية الواجهات
-
تسمح بتطبيق أشكال متعددة من الوراثة.
-
تسهّل الاختبارات البرمجية.
-
تدعم تصميم الأنظمة بطريقة أكثر مرونة وتوسعاً.
المبادئ التصميمية المرتبطة بـ OOP
مبدأ المسؤولية الواحدة (Single Responsibility Principle – SRP)
ينص هذا المبدأ على أن كل فئة يجب أن يكون لها سبب واحد فقط للتغيير، أي أن تؤدي وظيفة واحدة فقط بشكل دقيق.
csharppublic class ReportPrinter
{
public void Print(string content)
{
Console.WriteLine(content);
}
}
مبدأ الفتح/الإغلاق (Open/Closed Principle)
الفئات يجب أن تكون مفتوحة للإضافة ومغلقة للتعديل. يُعنى بذلك أنه يمكن توسيع وظائف الكود دون الحاجة إلى تغييره.
تطبيقات عملية للبرمجة كائنية التوجه في #C
مثال: نظام إدارة مكتبة
لتوضيح كيفية دمج المفاهيم السابقة في مشروع متكامل، يمكن تصميم نظام بسيط لإدارة مكتبة باستخدام OOP:
csharppublic abstract class LibraryItem
{
public string Title { get; set; }
public string Author { get; set; }
public abstract void DisplayInfo();
}
public class Book : LibraryItem
{
public override void DisplayInfo()
{
Console.WriteLine($"Book: {Title}, Author: {Author}");
}
}
public class DVD : LibraryItem
{
public override void DisplayInfo()
{
Console.WriteLine($"DVD: {Title}, Director: {Author}");
}
}
هذا التصميم يسمح بإضافة أنواع جديدة من المواد مثل المجلات أو الأقراص الصوتية بسهولة من خلال إنشاء فئات جديدة ترث من LibraryItem.
الجدول: مقارنة بين الفئات المجردة والواجهات في #C
| الخاصية | الفئة المجردة (Abstract Class) | الواجهة (Interface) |
|---|---|---|
| يمكنها احتواء تنفيذ | نعم | لا (حتى C# 7.3) |
| يدعم الخصائص | نعم | نعم |
| التعدد في الوراثة | لا | نعم |
| هدف الاستخدام الرئيسي | مشاركة الكود | تحديد العقود (Contracts) |
| الإنشاء المباشر | لا | لا |
أهمية OOP في المشاريع الكبيرة
تعتمد معظم الأنظمة البرمجية الكبرى اليوم على مبادئ البرمجة كائنية التوجه، نظرًا لقدرتها على:
-
تحسين قابلية الصيانة وإعادة الاستخدام.
-
دعم نماذج التطوير المتكررة مثل Agile وScrum.
-
تسهيل اختبار الوحدات Unit Testing بفضل الاعتماد على الواجهات والتعددية.
-
تسهيل التوسع وإضافة خصائص جديدة دون التأثير على الشيفرة الأساسية.
الخلاصة
يمثل هذا الجزء الثاني من موضوع “تطبيق البرمجة كائنية التوجه في لغة سي شارب #C” توسعًا في مفاهيم OOP وتطبيقاتها المتقدمة التي تُعتبر حجر الأساس في تصميم الأنظمة الحديثة. من خلال فهم التوريث والتعددية والتغليف والواجهات والفئات المجردة، يستطيع المطور تصميم حلول برمجية أكثر قوة ومرونة وقابلية للتوسع. يوصى بممارسة هذه المفاهيم في مشاريع حقيقية للحصول على خبرة عملية أعمق.
المراجع
-
Microsoft Docs – Object-Oriented Programming (C#)
-
“C# in Depth” by Jon Skeet – 4th Edition

