المنشئ Constructor في Java

16:00 دقائق مجاني

لماذا نحتاج Constructor؟ وكيف يهيّئ الكائن تلقائياً عند إنشائه؟ وما الفرق بينه وبين الدوال العادية؟ مع أمثلة عملية مفصّلة.

المشكلة — لماذا نحتاج Constructor؟

في الدرس السابق أنشأنا كائناً ثم بدأنا نضع القيم يدوياً — سطراً سطراً:

⚠️ الطريقة القديمة — مزعجة مع خصائص كثيرة
Person p1 = new Person();
p1.name   = "Ahmed";
p1.age    = 25;
p1.email  = "ahmed@example.com";
p1.city   = "Riyadh";
p1.salary = 5000;
// 5 أسطر فقط لإنشاء شخص واحد — وقد ننسى خاصية!

هذا صحيح، لكنه يصبح مرهقاً مع كثرة الخصائص. هنا يأتي دور المنشئ (Constructor) — يهيّئ الكائن بكل قيمه دفعة واحدة عند إنشائه.

😫

بدون Constructor

سطر لكل خاصية — يمكن نسيان تعبئة خاصية مهمة

😊

مع Constructor

سطر واحد — الكائن جاهز بكل بياناته فوراً

ما هو Constructor وكيف نتعرّف عليه؟

المنشئ يشبه الدالة لكنه خاص جداً — يعمل تلقائياً في اللحظة التي تكتب فيها new Person(...).

الفرق بين Constructor والدالة العادية:

الميزة Constructor دالة عادية
الاسم نفس اسم الكلاس تماماً أي اسم تختاره
نوع الإرجاع لا يوجد (لا void ولا int) void أو int أو String...
وقت التشغيل تلقائياً عند new عند استدعائها يدوياً
الهدف تهيئة الكائن فقط أي غرض تريده
💡

تشبيه: Constructor مثل استمارة التسجيل التي تملأها عند التسجيل في موقع — تُملأ مرة واحدة وتكون بياناتك جاهزة فوراً.

كيف نكتب Constructor؟

سننشئ Constructor للكلاس Person يستقبل الاسم والعمر عند إنشاء الكائن مباشرةً:

Person.java
class Person {
    // الخصائص
    String name;
    int    age;

    // ← المنشئ Constructor
    Person(String n, int a) {
        name = n;   ← خزّن n في name
        age  = a;   ← خزّن a في age
    }
}
Person

اسم Constructor = اسم الكلاس

لاحظ أن اسم المنشئ هو Person — نفس اسم الكلاس بالضبط، وهذا إلزامي.

String n

المدخلات (Parameters)

نستقبل قيمتين: n للاسم و a للعمر. سنمررهما عند الإنشاء.

name = n

تعيين القيم للخصائص

نأخذ القيمة الواردة n ونخزّنها في خاصية الكائن name.

كيف نستخدم Constructor عند إنشاء الكائن؟

الآن بدل 3 أسطر منفصلة، يمكننا إنشاء الشخص بسطر واحد:

❌ قبل Constructor

Person p1 = new Person();
p1.name = "Ahmed";
p1.age  = 25;
// 3 أسطر

✅ مع Constructor

Person p1 = new Person("Ahmed", 25);
// سطر واحد فقط! ✨
Main.java
// إنشاء كائنات بسطر واحد لكل منها
Person p1 = new Person("Ahmed", 25);
Person p2 = new Person("Sara",  20);
Person p3 = new Person("Ali",   30);

System.out.println(p1.name + " - " + p1.age);
System.out.println(p2.name + " - " + p2.age);
🖥️
Ahmed - 25
Sara - 20

🔍 ماذا يحدث خطوة بخطوة عند كتابة new Person("Ahmed", 25)؟

1 Java تنشئ كائناً جديداً في الذاكرة من نوع Person
2 تبحث عن Constructor يقبل (String, int) وتجده
3 تمرر "Ahmed" إلى المعامل n و 25 إلى المعامل a
4 ينفّذ name = n و age = a فيُخزّن الاسم والعمر
الكائن p1 جاهز للاستخدام فوراً بكل بياناته

الكلمة المحجوزة this — أفضل طريقة للكتابة

في المثال السابق استخدمنا أسماء مختلفة للمعاملات (n و a) لتجنب التشابه مع الخصائص. لكن المبرمجون المحترفون يستخدمون نفس الأسماء مع الكلمة المحجوزة this.

💡

this تعني "هذا الكائن الحالي" — تُستخدم للتمييز بين خاصية الكائن والمعامل اللي له نفس الاسم.

بدون this (أسماء مختلفة)

Person(String n, int a) {
    name = n;
    age  = a;
}

مع this (نفس الأسماء — أوضح)

Person(String name, int age) {
    this.name = name;
    this.age  = age;
}

ما معنى this.name = name؟

this.name

= خاصية الكائن الحالي المسماة name

name

= المعامل (Argument) الوارد للConstructor

this.name = name تعني: خذ القيمة الواردة في المعامل name وخزّنها في خاصية name الخاصة بهذا الكائن.

لماذا Constructor مهم؟ — الفوائد

كود أقصر وأوضح

بدل 4 أسطر لكل كائن، تصبح سطراً واحداً. مع 10 كائنات، الفرق يصبح واضحاً جداً.

🔒

يُجبر على تعبئة البيانات الأساسية

إذا كان Constructor يطلب name و age — لا يمكنك إنشاء كائن بدون تمريرهما. هذا يمنع نسيان خاصية مهمة.

🎯

الكائن جاهز للاستخدام فوراً

بعد سطر الإنشاء مباشرةً، يمكنك استخدام p1.name و p1.age بثقة — لا تحتاج تتحقق هل تم تعبئتها أم لا.

📌 ملاحظة متقدمة

يمكن أن يوجد أكثر من Constructor في نفس الكلاس بمدخلات مختلفة — هذا يُسمى Constructor Overloading. مثلاً constructor بدون مدخلات وآخر بمدخلين. سنتعلم هذا في المستويات القادمة.

أخطاء شائعة عند المبتدئين ⚠️

خطأ ١

كتابة نوع إرجاع للConstructor

❌ خطأ

void Person(String name) {

أصبح دالة عادية وليس Constructor!

✅ صحيح

Person(String name) {

بدون void أو أي نوع إرجاع

خطأ ٢

اسم Constructor لا يطابق اسم الكلاس

❌ خطأ

class Person { person(String n) { }

person بحرف صغير ≠ Person

✅ صحيح

class Person { Person(String n) { }
خطأ ٣

تمرير عدد قيم مختلف عن المطلوب

❌ خطأ

Person(String n, int a) {...} new Person("Ahmed");

Constructor يطلب 2 قيم — أعطيته 1

✅ صحيح

Person(String n, int a) {...} new Person("Ahmed", 25);

📋 ملخص الدرس

Constructor يهيّئ الكائن تلقائياً عند new

اسمه = اسم الكلاس — بدون نوع إرجاع

this.name للتمييز بين خاصية الكائن والمعامل

يجبر على تعبئة البيانات الأساسية منذ البداية

⏭️ في الدرس القادم:

سنتعلم Encapsulation (التغليف) — كيف نحمي بيانات الكائن بحيث لا يعبث بها أي جزء من البرنامج بشكل مباشر، باستخدام private و getter/setter.

الدرس التالي العودة للسابق