كيفية استدعاء مُنشئ من مُنشئ آخر في Java: تفاصيل غير واضحة ستغير كودك
هل سبق لك أن كتبت فئة Java تحتوي على 5-6 مُنشئات وشعرت أنك تغرق في تكرار الكود؟ أو على العكس، نظرت إلى كود شخص آخر حيث يظهر this(name, 0, true) الغامض وتساءلت: "ما هذا السحر؟".
السؤال "How do I call one constructor from another in Java?" هو أحد أكثر الأسئلة شيوعًا على Stack Overflow (آلاف المشاهدات ومئات الإجابات). وهذا ليس بدون سبب. فالعملية التي تبدو بسيطة - استدعاء مُنشئ - تخفي الكثير من الفروق الدقيقة التي تؤثر على الأداء، وقابلية القراءة، وحتى صحة عمل البرنامج.
في هذه المقالة، لن نعرض فقط بناء الجملة. سننظر تحت غطاء JVM، ونحلل كيف يعالج المترجم هذه الاستدعاءات، ونقدم نصائح عملية تفيد المبتدئ والمطور المتمرس على حد سواء.
لماذا استدعاء مُنشئ من مُنشئ آخر؟ مشكلة التكرار
تخيل أنك تكتب فئة User، تحتوي على حقول إلزامية (الاسم، البريد الإلكتروني) وحقول اختيارية (العمر، رقم الهاتف). تريد منح مستخدمي API الخاص بك المرونة: إنشاء كائن بأقل مجموعة بيانات أو بكل التفاصيل.
النهج السيئ (بدون استدعاء مُنشئ):
public class User { private String name; private String email; private int age; private String phone;
public User(String name, String email) { this.name = name; this.email = email; this.age = 0; // القيمة الافتراضية this.phone = null; // القيمة الافتراضية }
public User(String name, String email, int age) { this.name = name; this.email = email; this.age = age; this.phone = null; // تكرار مرة أخرى }
public User(String name, String email, int age, String phone) { this.name = name; this.email = email; this.age = age; this.phone = phone; }}هنا نقوم بتعيين name و email ثلاث مرات. عند إضافة حقل جديد، سيتعين تعديل جميع المُنشئات. هذا ينتهك مبدأ DRY (Don't Repeat Yourself) ويزيد من خطر الأخطاء.
النهج الجيد (مع استدعاء المُنشئ عبر this()):
public class User { private String name; private String email; private int age; private String phone;
public User(String name, String email) { this(name, email, 0, null); // تفويض إلى المُنشئ "الأكثر اكتمالاً" }
public User(String name, String email, int age) { this(name, email, age, null); // تفويض مرة أخرى }
public User(String name, String email, int age, String phone) { this.name = name; this.email = email; this.age = age; this.phone = phone; }}الآن كل منطق التهيئة موجود في مُنشئ واحد. البقية فقط تفوض العمل إليه، وتمرر القيم الافتراضية. هذا موجز، وسهل الصيانة، ويقلل فرصة نسيان حقل.
بناء جملة استدعاء المُنشئ: this() و super()
في Java، هناك كلمتان رئيسيتان لاستدعاء المُنشئات:
this(المعلمات)- يستدعي مُنشئًا آخر من نفس الفئة.super(المعلمات)- يستدعي مُنشئ الفئة الأم.
القاعدة الأهم: يجب أن يكون استدعاء this() أو super() هو العبارة الأولى في المُنشئ. لماذا؟ سنشرح ذلك لاحقًا.
مثال مع الوراثة:
class Animal { private String species;
public Animal(String species) { this.species = species; System.out.println("Animal constructor: " + species);