البرمجة

مقدمة للبرمجة كائنية التوجه بـ C#

تطبيق البرمجة كائنية التوجه في لغة سي شارب #C – الجزء الأول

تُعتبر البرمجة كائنية التوجه (Object-Oriented Programming – OOP) واحدة من أهم المفاهيم البرمجية التي أسهمت في تطوير البرمجيات بشكل كبير، حيث توفر نموذجاً تنظيمياً يساعد في كتابة برامج أكثر وضوحاً وقابلية للصيانة والتطوير. لغة سي شارب #C، والتي تم تطويرها بواسطة مايكروسوفت، هي واحدة من اللغات التي تعتمد بشكل رئيسي على هذا النموذج، حيث توفر دعماً واسعاً لمبادئ البرمجة كائنية التوجه مثل التغليف، الوراثة، والتعدد الشكلي.

مقدمة إلى البرمجة كائنية التوجه

البرمجة كائنية التوجه هي طريقة في تطوير البرمجيات تعتمد على تقسيم البرامج إلى كائنات (Objects) تمثل وحدات مستقلة تحتوي على بيانات وسلوكيات (خصائص ودوال). هذه الطريقة تسمح بتمثيل الواقع بشكل أقرب إلى الطبيعة، حيث يمكن لكل كائن أن يمتلك حالته الخاصة ويتفاعل مع كائنات أخرى ضمن النظام البرمجي.

تُركّز البرمجة كائنية التوجه على أربعة مفاهيم أساسية:

  • التغليف (Encapsulation): إخفاء تفاصيل التنفيذ الداخلية للكائن بحيث لا يستطيع الخارج الوصول إليها مباشرة، ويتم التحكم فيها فقط من خلال واجهة محددة.

  • الوراثة (Inheritance): إمكانية إنشاء كائنات جديدة تستمد خصائصها وسلوكياتها من كائنات موجودة، مما يتيح إعادة الاستخدام وتوسيع الوظائف.

  • التعدد الشكلي (Polymorphism): القدرة على استخدام واجهات متعددة للكائن الواحد، أو القدرة على استدعاء نفس الدالة بأشكال مختلفة حسب نوع الكائن.

  • التجريد (Abstraction): التركيز على الخصائص الأساسية للكائن دون التعقيد في التفاصيل غير المهمة.

لغة سي شارب ودعمها للبرمجة كائنية التوجه

تم تصميم لغة #C لتكون لغة برمجة حديثة ومتعددة الاستخدامات، تجمع بين قوة الأداء وسهولة التعلم، وهي تعتمد بشكل كبير على البرمجة كائنية التوجه، مما يجعلها مناسبة لتطوير تطبيقات سطح المكتب، تطبيقات الويب، تطبيقات الهواتف الذكية، الألعاب، والأنظمة المعقدة.

توفر #C مجموعة كبيرة من الميزات التي تدعم البرمجة كائنية التوجه بشكل فعال، منها:

  • الفئات (Classes) والكائنات (Objects): الفئة هي القالب الأساسي الذي يُنشأ منه الكائن. يمكن تعريف الفئات لتحتوي على خصائص (Properties) ودوال (Methods) لتعريف سلوك الكائن.

  • الواجهات (Interfaces): تتيح تحديد مجموعة من الدوال التي يجب أن تنفذها الفئة التي تعتمد هذه الواجهة، مما يدعم تصميم البرمجيات بشكل مرن وقابل للتوسعة.

  • الوراثة: يمكن للفئات أن ترث من فئات أخرى، ما يسمح بإعادة استخدام الشيفرة وتنظيمها بشكل أفضل.

  • المُوَصِّفون (Constructors) والمُدمِّرون (Destructors): تُستخدم لتهيئة الكائنات عند إنشائها والتحكم في عملية تدميرها.

  • الخصائص (Properties): تقدم طريقة آمنة للوصول إلى بيانات الكائن مع التحكم في كيفية تعيينها أو الحصول عليها.

  • التعدد الشكلي من خلال تعدد الدوال (Method Overloading) وتعدد الأشكال عبر الطرازات (Polymorphism via Virtual Methods): تسمح للبرمجة بأن تكون أكثر مرونة.

إنشاء فئة وكائن في #C

لفهم كيفية تطبيق البرمجة كائنية التوجه في #C، من الضروري البدء بإنشاء فئة بسيطة، ثم إنشاء كائن منها. على سبيل المثال:

csharp
public class Person { // خاصية لتخزين اسم الشخص public string Name { get; set; } // خاصية لتخزين عمر الشخص public int Age { get; set; } // مُوَصِّف يقوم بتهيئة الكائن عند إنشائه public Person(string name, int age) { Name = name; Age = age; } // دالة تعرض معلومات الشخص public void DisplayInfo() { Console.WriteLine($"Name: {Name}, Age: {Age}"); } }

في المثال السابق، الفئة Person تحتوي على خاصيتين Name و Age، بالإضافة إلى مُوَصِّف (Constructor) يهيئ هاتين الخاصيتين عند إنشاء كائن جديد. كما تتضمن دالة DisplayInfo لعرض معلومات الكائن.

لإنشاء كائن من هذه الفئة واستخدامه:

csharp
Person person1 = new Person("Ahmed", 30); person1.DisplayInfo();

النتيجة ستكون طباعة الاسم والعمر على الشاشة.

مفهوم التغليف في #C

التغليف يعني حماية بيانات الكائن وعدم السماح بالوصول المباشر إليها من خارج الفئة، حيث يتم استخدام الخصائص (Properties) للتحكم في الوصول إلى البيانات. هذا يمنع الأخطاء الناتجة عن تعديل البيانات بشكل غير صحيح.

في المثال السابق، تم استخدام خاصيات ذات الوصول العام (public)، ولكن لتحسين التغليف يمكن جعل الحقول خاصة (private) واستخدام خصائص للتحكم في الوصول، كما يلي:

csharp
public class Person { private string name; private int age; public string Name { get { return name; } set { if (!string.IsNullOrEmpty(value)) name = value; } } public int Age { get { return age; } set { if (value >= 0) age = value; } } public Person(string name, int age) { Name = name; Age = age; } public void DisplayInfo() { Console.WriteLine($"Name: {Name}, Age: {Age}"); } }

بهذا الشكل، تتحقق الفئة من صحة القيم قبل تعيينها، ما يعزز أمان البيانات داخل الكائن.

الوراثة في #C

الوراثة تسمح للفئة الجديدة أن ترث خصائص وسلوكيات من فئة موجودة، مما يعزز إعادة استخدام الشيفرة ويقلل من التكرار. الفئة التي ترث تسمى “فئة مشتقة” (Derived Class)، والفئة التي يتم الوراثة منها تسمى “فئة أساسية” (Base Class).

على سبيل المثال، إذا أردنا إنشاء فئة جديدة تمثل موظفًا (Employee) ترث من فئة الشخص (Person):

csharp
public class Employee : Person { public string Position { get; set; } public Employee(string name, int age, string position) : base(name, age) // استدعاء المُوَصِّف الأساسي للفئة Person { Position = position; } public void DisplayEmployeeInfo() { DisplayInfo(); Console.WriteLine($"Position: {Position}"); } }

هنا، فئة Employee ترث كل الخصائص والدوال من فئة Person، وتضيف خاصية جديدة هي Position ودالة جديدة لعرض المعلومات الخاصة بالموظف.

عند إنشاء كائن من فئة Employee:

csharp
Employee emp = new Employee("Sara", 28, "Software Developer"); emp.DisplayEmployeeInfo();

سوف تُعرض معلومات الاسم، العمر، والوظيفة.

التعدد الشكلي في #C

التعدد الشكلي هو قدرة الكائنات على الاستجابة للدوال بنفس الاسم بطرق مختلفة، وهذا يتحقق في #C من خلال استخدام الدوال الافتراضية (virtual) وإعادة تعريفها (override).

مثلاً، في فئة أساسية يمكن تعريف دالة عرض المعلومات بشكل عام، ثم في الفئة المشتقة يمكن تعديل هذه الدالة لتوفير تفاصيل إضافية.

csharp
public class Person { public string Name { get; set; } public int Age { get; set; } public Person(string name, int age) { Name = name; Age = age; } public virtual void DisplayInfo() { Console.WriteLine($"Name: {Name}, Age: {Age}"); } } public class Employee : Person { public string Position { get; set; } public Employee(string name, int age, string position) : base(name, age) { Position = position; } public override void DisplayInfo() { base.DisplayInfo(); // استدعاء الدالة من الفئة الأساسية Console.WriteLine($"Position: {Position}"); } }

بهذه الطريقة، يمكن استدعاء دالة DisplayInfo على كائن من نوع Person أو Employee، وستتصرف بناءً على نوع الكائن.

الواجهات (Interfaces) في #C

الواجهة تمثل عقداً يحدد مجموعة من الدوال التي يجب على الفئة التي تعتمد هذه الواجهة تنفيذها. استخدام الواجهات يعزز من قابلية التوسعة والتعديل، حيث يمكن لفئات مختلفة تنفيذ نفس الواجهة بطرق مختلفة.

مثال على تعريف واجهة:

csharp
public interface IPrintable { void Print(); }

ثم فئة تعتمد هذه الواجهة:

csharp
public class Document : IPrintable { public string Content { get; set; } public Document(string content) { Content = content; } public void Print() { Console.WriteLine(Content); } }

باستخدام الواجهات، يمكن التعامل مع كائنات مختلفة تشترك في نفس السلوك (مثل الطباعة) بدون معرفة التفاصيل الداخلية لكل فئة.

التجريد (Abstraction) في #C

التجريد يسمح بإنشاء فئات مجردة لا يمكن إنشاء كائن منها مباشرة، بل تُستخدم كقاعدة لفئات أخرى، تحتوي على تعريفات دوال مجردة يجب على الفئات المشتقة تنفيذها.

مثال:

csharp
public abstract class Shape { public abstract double GetArea(); } public class Circle : Shape { public double Radius { get; set; } public Circle(double radius) { Radius = radius; } public override double GetArea() { return Math.PI * Radius * Radius; } }

الفئة Shape تحتوي على دالة مجردة GetArea، ويجب على الفئات المشتقة مثل Circle تنفيذ هذه الدالة.

مثال تطبيقي شامل

لشرح كيفية تطبيق جميع المفاهيم السابقة، يمكن إنشاء نظام لإدارة الموظفين في شركة، يشمل فئات للموظفين، والأقسام، والرواتب.

الفئات الأساسية:

  • Person: تحتوي على الخصائص الأساسية مثل الاسم والعمر.

  • Employee: ترث من Person وتحتوي على معلومات إضافية مثل الوظيفة والراتب.

  • Department: تحتوي على قائمة من الموظفين.

نموذج الكود:

csharp
public class Person { public string Name { get; set; } public int Age { get; set; } public Person(string name, int age) { Name = name; Age = age; } public virtual void DisplayInfo() { Console.WriteLine($"Name: {Name}, Age: {Age}"); } } public class Employee : Person { public string Position { get; set; } public double Salary { get; set; } public Employee(string name, int age, string position, double salary) : base(name, age) { Position = position; Salary = salary; } public override void DisplayInfo() { base.DisplayInfo(); Console.WriteLine($"Position: {Position}, Salary: {Salary:C}"); } } public class Department { public string DepartmentName { get; set; } private List employees = new List(); public Department(string name) { DepartmentName = name; } public void AddEmployee(Employee employee) { employees.Add(employee); } public void DisplayDepartmentInfo() { Console.WriteLine($"Department: {DepartmentName}"); foreach (var emp in employees) { emp.DisplayInfo(); Console.WriteLine("-----------------"); } } }

كيفية استخدام النظام:

csharp
Department devDept = new Department("Development"); Employee emp1 = new Employee("Ali", 35, "Senior Developer", 9000); Employee emp2 = new Employee("Nour", 29, "Junior Developer", 5000); devDept.AddEmployee(emp1); devDept.AddEmployee(emp2); devDept.DisplayDepartmentInfo();

هذا المثال يوضح كيفية تنظيم الكائنات والعلاقات بينها باستخدام البرمجة كائنية التوجه، مما يسهل إدارة بيانات الموظفين بطريقة منظمة ومرنة.

أهمية البرمجة كائنية التوجه في تطوير البرمجيات باستخدام #C

الاعتماد على البرمجة كائنية التوجه في تطوير البرمجيات بلغة #C يوفر عدداً من الفوائد الجوهرية، أهمها:

  • إعادة الاستخدام: يمكن إعادة استخدام الفئات والكود في مشاريع أخرى، مما يقلل الجهد والوقت.

  • التنظيم: تنظيم الكود في وحدات مستقلة يسهل فهمه وتعديله.

  • الصيانة: سهولة تعديل جزء معين من الكود دون التأثير على بقية النظام.

  • التوسع: إمكانية إضافة ميزات جديدة بسهولة من خلال الوراثة أو إضافة فئات جديدة.

  • المرونة: دعم التعدد الشكلي يجعل النظام قادرًا على التكيف مع متطلبات مختلفة دون تغيير هيكل الكود الأساسي.

الخلاصة

البرمجة كائنية التوجه تمثل نموذجاً برمجياً متكاملاً يعزز من تطوير البرمجيات عالية الجودة. لغة #C توفر بنية قوية ومرنة تدعم هذا النموذج، مما يجعلها خياراً مفضلاً لتطوير مختلف أنواع التطبيقات. من خلال فهم المفاهيم الأساسية مثل الفئات، الكائنات، التغليف، الوراثة، التعدد الشكلي، والتجريد، يمكن للمطورين بناء نظم برمجية متينة وقابلة للتطوير، تسهل عمليات الصيانة والتوسع. في الجزء الأول من هذا المقال تم استعراض المبادئ الأساسية وأمثلة تطبيقية تساعد على البدء في البرمجة كائنية التوجه بلغة #C بشكل عملي ومنهجي.


المصادر والمراجع