C#: الفئات والكائنات

1. لماذا نحتاج إلى الفئات؟

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


2. تعريف الفئة

استخدم الكلمة الرئيسية class لتعريف فئة. تُكتب أسماء الفئات باستخدام أسلوب PascalCase (بكتابة الحرف الأول من كل كلمة بحرف كبير).

CSHARP
class Person
{
    public string Name;
    public int Age;

    public void SayHello()
    {
        System.Console.WriteLine($"Hello, I'm {Name}, {Age} years old.");
    }
}

3. إنشاء الكائنات

استخدم الكلمة الرئيسية new لإنشاء كائن من فئة:

CSHARP
Person p = new Person();
p.Name = "Tom";
p.Age = 18;
p.SayHello();
TEXT 📖 للعرض فقط
Hello, I'm Tom, 18 years old.

يقوم كل new بإنشاء كائن مستقل يحتوي على نسخة خاصة به من الحقول.


4. الحقول وتهيئة الحقول

يمكن تعيين قيم أولية للحقول عند الإعلان عنها:

CSHARP
class Student
{
    public string Name = "Unknown";
    public int Score = 0;
}

في حالة عدم تعيين أي قيمة أولية، تُعيَّن القيمة الافتراضية للأنواع الرقمية إلى 0، بينما تُعيَّن القيمة الافتراضية للأنواع المرجعية إلى null.

تتحكم مُعدِّلات الوصول في ظهور الحقول:

المُعدِّل المعنى
public يمكن الوصول إليه من أي مكان
private لا يمكن الوصول إليها إلا داخل الفئة (الافتراضي)

عادةً ما يتم تعيين الحقول إلى private، ويتم التحكم في الوصول إليها من خلال الطرق أو الخصائص.

▶ مثال

CSHARP
using System;

class BankAccount
{
    private decimal balance = 1000m;

    public void Deposit(decimal amount)
    {
        balance += amount;
        Console.WriteLine($"Deposited {amount}, balance is {balance}");
    }

    public void ShowBalance()
    {
        Console.WriteLine($"Current balance: {balance}");
    }
}

class Program
{
    static void Main()
    {
        BankAccount acc = new BankAccount();
        acc.ShowBalance();
        acc.Deposit(500m);
    }
}
▶ جرّب الكود
TEXT 📖 للعرض فقط
Current balance: 1000
Deposited 500, balance is 1500

5. الطرق

الطرق هي دالات مُعرَّفة داخل فئة ما وتصف سلوك الكائن. يمكن للطرق الوصول إلى الحقول الموجودة داخل الفئة نفسها:

CSHARP
class Calculator
{
    private int result = 0;

    public void Add(int value)
    {
        result += value;
    }

    public int GetResult()
    {
        return result;
    }
}

6. الكلمة الرئيسية «this»

يشير this إلى مثيل الكائن الحالي. ويُستخدم في الغالب لتمييز الحقول عن المعلمات التي تحمل الاسم نفسه:

CSHARP
class Person
{
    public string Name;
    public int Age;

    public Person(string Name, int Age)
    {
        this.Name = Name;
        this.Age = Age;
    }
}

7. منشئات

يتم استدعاء منشئات الكائنات تلقائيًا عند إنشاء كائن ما، وتُستخدم لتهيئة الكائن.

(1) مُنشئ بدون معلمات

في حالة عدم تعريف أي مُنشئ، يقوم المُترجم تلقائيًا بإنشاء مُنشئ بدون معلمات:

CSHARP
class Dog
{
    public string Name;

    public Dog()
    {
        Name = "Unnamed";
    }
}

(2) مُنشئ مُعَرَّف بالمعلمات

CSHARP
class Dog
{
    public string Name;

    public Dog(string name)
    {
        Name = name;
    }
}

⚠️ بمجرد تعريف أي مُنشئ، لن يقوم المُترجم بعد ذلك تلقائيًا بإنشاء مُنشئ بدون معلمات.

(3) تحميل الدالة البانية

يمكنك تعريف عدة منشئات بمعلمات مختلفة:

CSHARP
class Dog
{
    public string Name;
    public int Age;

    public Dog()
    {
        Name = "Unnamed";
        Age = 0;
    }

    public Dog(string name)
    {
        Name = name;
        Age = 0;
    }

    public Dog(string name, int age)
    {
        Name = name;
        Age = age;
    }
}

(4) تسلسل المنشئات

استخدم this(...) لجعل أحد المنشئات يستدعي منشئًا آخر، مما يتيح تجنب تكرار الكود:

CSHARP
class Dog
{
    public string Name;
    public int Age;

    public Dog() : this("Unnamed", 0) { }

    public Dog(string name) : this(name, 0) { }

    public Dog(string name, int age)
    {
        Name = name;
        Age = age;
    }
}

▶ مثال

CSHARP
using System;

class Book
{
    public string Title;
    public string Author;
    public decimal Price;

    public Book() : this("Unknown", "Unknown", 0m) { }

    public Book(string title, string author) : this(title, author, 29.9m) { }

    public Book(string title, string author, decimal price)
    {
        Title = title;
        Author = author;
        Price = price;
    }

    public void PrintInfo()
    {
        Console.WriteLine($"\"{Title}\" Author: {Author} Price: {Price}");
    }
}

class Program
{
    static void Main()
    {
        Book b1 = new Book();
        Book b2 = new Book("C# Basics", "Alice");
        Book b3 = new Book("Advanced C#", "Bob", 59.9m);

        b1.PrintInfo();
        b2.PrintInfo();
        b3.PrintInfo();
    }
}
▶ جرّب الكود
TEXT 📖 للعرض فقط
"Unknown" Author: Unknown Price: 0
"C# Basics" Author: Alice Price: 29.9
"Advanced C#" Author: Bob Price: 59.9

8. مُدمِّرات

يتم استدعاء مُدمِّر الكائن قبل أن يتم جمع القمامة الخاصة به. وصيغة الاستدعاء هي ~ClassName():

CSHARP
class Resource
{
    ~Resource()
    {
        Console.WriteLine("Object is being reclaimed");
    }
}

📌 تتميز لغة C# بوجود آلية تجميع القمامة التلقائية (GC)، لذا نادرًا ما تحتاج إلى كتابة دالة التدمير يدويًّا. ولا تُستخدم دوال التدمير إلا لتحرير الموارد غير المُدارة (مثل معالجات الملفات واتصالات قواعد البيانات)، وهو ما سيتم مناقشته بالتفصيل في الدروس اللاحقة.


9. مُهيِّئات الكائنات

قدمت لغة C# 3.0 صيغة مُهيِّئ الكائنات، والتي تتيح لك تعيين القيم مباشرةً إلى الحقول أو الخصائص العامة عند استخدام new:

CSHARP
Person p = new Person { Name = "Lily", Age = 20 };

وهذا يعادل:

CSHARP
Person p = new Person();
p.Name = "Lily";
p.Age = 20;

يمكن دمج مُهيِّئات الكائنات مع مُنشِئات الكائنات المعلمة:

CSHARP
Person p = new Person("Lily") { Age = 20 };

▶ مثال

CSHARP
using System;

class Rectangle
{
    public double Width = 1;
    public double Height = 1;

    public double Area()
    {
        return Width * Height;
    }
}

class Program
{
    static void Main()
    {
        Rectangle r1 = new Rectangle();
        Rectangle r2 = new Rectangle { Width = 5, Height = 3 };
        Rectangle r3 = new Rectangle { Width = 10 };

        Console.WriteLine($"r1 area: {r1.Area()}");
        Console.WriteLine($"r2 area: {r2.Area()}");
        Console.WriteLine($"r3 area: {r3.Area()}");
    }
}
▶ جرّب الكود
TEXT 📖 للعرض فقط
r1 area: 1
r2 area: 15
r3 area: 10

10. الفرق بين «new» و«null»

المفهوم المعنى
new ClassName() ينشئ كائنًا في الذاكرة المؤقتة، ويعيد مرجعًا إلى الكائن
null لا يشير إلى أي كائن، وهو القيمة الافتراضية لأنواع المرجع
CSHARP
Person p1 = new Person();
Person p2 = null;

Console.WriteLine(p1 == null);
Console.WriteLine(p2 == null);
TEXT 📖 للعرض فقط
False
True

⚠️ يؤدي الوصول إلى عنصر في مرجع null إلى ظهور خطأ NullReferenceException، وهو الخطأ الأكثر شيوعًا في وقت التشغيل في لغة C#:

CSHARP
Person p = null;
p.SayHello();

💡 تأكد من وجود null قبل الدخول:

CSHARP
if (p != null)
{
    p.SayHello();
}

❓ أسئلة شائعة

س ماذا يحدث إذا لم أكتب مُنشئًا؟
ج يقوم المُترجم تلقائيًّا بإنشاء مُنشئ بدون معلمات يُعيّن القيم الافتراضية للحقول.
س هل لا يزال بإمكاني إنشاء كائن بدون معلمات بعد تعريف منشئ معلمات؟
ج لا، ما لم تقم أيضًا بتعريف منشئ بدون معلمات يدويًّا.
س هل يمكن استخدام هذا في الطرق الثابتة؟
ج لا، فهذا يشير إلى المثيل الحالي، والطرق الثابتة لا ترتبط بأي مثيل.
س هل يمكن لمُهيِّئات الكائنات تعيين قيم للحقول الخاصة؟
ج لا، فهي لا تستطيع تهيئة سوى العناصر القابلة للوصول (الحقول العامة أو الخصائص).
س هل «null» و«0» هما نفس الشيء؟
ج لا. «null» تعني «عدم وجود مرجع»، بينما «0» هي قيمة من الأنواع العددية. ولا يمكن أن تكون القيم من الأنواع العددية «null».

📖 ملخص

📝 تمارين

  1. قم بتعريف فئة Car تحتوي على الحقول Brand (سلسلة) وSpeed (عدد صحيح)، وطريقة Accelerate(int amount) التي تزيد قيمة Speed، ومنشئ بدون معلمات يقوم بتهيئة قيمة Speed إلى 0
  2. أضف مُنشئًا معلماتيًّا Car(string brand) إلى الفئة Car، واستخدم this(...) لتنفيذ تسلسل المُنشئات
  3. استخدم مُهيئ الكائنات لإنشاء كائن Car وتعيين قيمتي «Brand» و«Speed»، ثم استدعاء الطريقة «Accelerate» وعرض قيمة «Speed» النهائية
  4. اكتب كودًا يوضح ما يلي: قم بإنشاء مرجع Car مُخصص لـ null، وحاول الوصول إلى أحد عناصره، واستخدم بنية try-catch لالتقاط الاستثناء NullReferenceException، ثم اطبع رسالة
Web-Tutorial.com

فريق Web-Tutorial التقني

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

100%