تسلسل المنشئات (Constructor Chaining)
جزء من قسم Object Oriented Programming في رحلة Java على Coddy — الدرس 23 من 87.
تسلسل المنشئات (Constructor chaining) هو عملية استدعاء منشئ من منشئ آخر. تساعد هذه التقنية في تجنب تكرار الكود عندما يحتوي الصنف (class) على منشئات متعددة أو عند العمل مع هياكل الوراثة (inheritance hierarchies).
داخل نفس الكلاس، يمكنك ربط المشيدات باستخدام this(). يتيح لك هذا الحصول على مشيد "رئيسي" واحد يقوم بكل العمل، بينما تقوم المشيدات الأخرى ببساطة بالتفويض إليه:
public class Rectangle {
private int width;
private int height;
public Rectangle() {
this(1, 1); // يستدعي المنشئ الذي يأخذ معاملين
}
public Rectangle(int size) {
this(size, size); // ينشئ مربعاً
}
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
}في الوراثة، يحدث تسلسل المنشئات (constructor chaining) تلقائيًا. عندما تقوم بإنشاء كائن من فئة فرعية (subclass)، يستدعي Java منشئ الفئة الأب أولاً باستخدام super(). إذا لم تقم باستدعاء super() صراحةً، يقوم Java بإدراج super() (النسخة التي لا تحتوي على وسائط) تلقائيًا:
public class Animal {
private String name;
public Animal(String name) {
this.name = name;
System.out.println("Animal constructor");
}
}
public class Dog extends Animal {
private String breed;
public Dog(String name, String breed) {
super(name); // يجب أن يكون السطر الأول
this.breed = breed;
System.out.println("Dog constructor");
}
}إنشاء new Dog("Buddy", "Labrador") يطبع "Animal constructor" أولاً، ثم "Dog constructor". يضمن ذلك تهيئة الفئات الأب (parent classes) بشكل صحيح دائماً قبل أن تضيف الفئة الابن (child class) إعداداتها الخاصة.
التحدي
سهللنقم ببناء نظام لطلب المنتجات يوضح تسلسل الاستدعاء للمنشئات (constructor chaining) داخل الفئة الواحدة وعبر تسلسل الوراثة. ستتعلم كيف يقوم this() بربط المنشئات في نفس الفئة، بينما يقوم super() بالربط بمنشئات الفئة الأب.
ستقوم بإنشاء ثلاثة ملفات لتنظيم الكود الخاص بك:
Product.java: أنشئ فئة أب تمثل أي منتج في المتجر. يجب أن تحتوي على:- حقول خاصة (Private fields) لـ
name(String) وprice(double) - منشئ رئيسي يأخذ كلاً من الاسم والسعر، ويقوم بتهيئة الحقول، ويطبع:
Product constructor: [name] - منشئ ثانٍ يأخذ الاسم فقط ويقوم بالربط بالمنشئ الرئيسي باستخدام
this(name, 0.0)لتعيين سعر افتراضي قدره 0.0 - دوال
getName()وgetPrice()للوصول إلى الحقول
- حقول خاصة (Private fields) لـ
Electronics.java: أنشئ فئة فرعية (subclass) ترث من Product وتضيف معلومات الضمان:- حقل خاص لـ
warrantyYears(int) - منشئ رئيسي يأخذ الاسم، والسعر، و warrantyYears - استخدم
super(name, price)لتهيئة الفئة الأب، ثم قم بتعيين الضمان واطبع:Electronics constructor: [warrantyYears] year warranty - منشئ ثانٍ يأخذ الاسم والسعر فقط، ويقوم بالربط بالمنشئ الرئيسي باستخدام
this(name, price, 1)لتوفير ضمان افتراضي لمدة عام واحد - منشئ ثالث يأخذ الاسم فقط، ويقوم بالربط بالمنشئ الثاني باستخدام
this(name, 0.0) - دالة
getDetails()تعيد:[name] - $[price] ([warrantyYears] year warranty)
- حقل خاص لـ
Main.java: استعرض تسلسل استدعاء المنشئات أثناء العمل. ستتلقى ثلاثة مدخلات: اسم المنتج (String)، والسعر (double)، وسنوات الضمان (int). أنشئ كائن Electronics باستخدام المعاملات الثلاثة، ثم اطبع نتيجةgetDetails().
ستتلقى ثلاثة مدخلات: اسم المنتج، والسعر، وسنوات الضمان.
قم بتنسيق السعر في getDetails() ليظهر بمنزلتين عشريتين باستخدام String.format("%.2f", price). راقب المخرجات بعناية - سترى رسائل المنشئات تظهر بالترتيب، مما يوضح كيف يتدفق التسلسل من الأب إلى الابن!
ورقة مرجعية
تسلسل المنشئات (Constructor chaining) هو عملية استدعاء منشئ من منشئ آخر لتجنب تكرار الكود.
التسلسل داخل نفس الفئة
استخدم this() لاستدعاء منشئ آخر في نفس الفئة:
public class Rectangle {
private int width;
private int height;
public Rectangle() {
this(1, 1); // Calls the two-parameter constructor
}
public Rectangle(int size) {
this(size, size); // Creates a square
}
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
}التسلسل في الوراثة
استخدم super() لاستدعاء منشئ الفئة الأب. يجب أن يكون السطر الأول في المنشئ:
public class Animal {
private String name;
public Animal(String name) {
this.name = name;
System.out.println("Animal constructor");
}
}
public class Dog extends Animal {
private String breed;
public Dog(String name, String breed) {
super(name); // Must be first line
this.breed = breed;
System.out.println("Dog constructor");
}
}إذا لم تقم باستدعاء super() صراحةً، فإن Java تقوم تلقائيًا بإدراج super() (النسخة التي لا تحتوي على وسائط). يتم دائمًا استدعاء منشئات الفئة الأب قبل منشئات الفئة الابن، مما يضمن ترتيب التهيئة الصحيح.
جرّب بنفسك
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// قراءة المدخلات
String name = scanner.nextLine();
double price = scanner.nextDouble();
int warrantyYears = scanner.nextInt();
// TODO: إنشاء كائن Electronics باستخدام جميع المعاملات الثلاثة
// TODO: طباعة نتيجة getDetails()
}
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس Object Oriented Programming
1أساسيات الـ OOP
الملفات الخارجيةمقدمة في الـ OOPالفئات (Classes) مقابل الكائنات (Objects)الكلمة المفتاحية thisالدوال (Methods)الحقول (Attributes)دالة البناء (Constructor)تعدد أشكال دالة البناء (Constructor Overloading)مراجعة - آلة حاسبة بسيطة4الوراثة
الوراثة الأساسية (extends)الكلمة المفتاحية superإعادة تعريف الدوال (@Override)تسلسل المنشئات (Constructor Chaining)كلاس Objectالوراثة الأحادية ومتعددة المستوياتلماذا لا توجد وراثة متعددة للكلاساتمراجعة - هيكلية الموظفين7الدوال الخاصة وفئة Object
دالة toString()equals() و hashCode()دالة clone()compareTo() و Comparableواجهة Comparatorمراجعة - الترتيب المخصص2محددات الوصول والتغليف
نظرة عامة على مستويات الوصولدوال Getter و Setterإخفاء البياناتالكلمة المفتاحية finalمراجعة - مدير الحساب البنكي5تعدد الأشكال (Polymorphism)
أساسيات الـ Method Overloadingالـ Method Overriding (في وقت التشغيل)الـ Upcasting والـ Downcastingمعامل الـ instanceofالفئات والدوال المجردة (Abstract)مراجعة - حاسبة الأشكال8مفاهيم OOP المتقدمة
الـ Composition مقابل الـ Inheritanceالـ Aggregation مقابل الـ Compositionالفئات الداخلية والمتداخلة والمجهولة (Inner, Nested & Anonymous)الـ Enums ودوالهاالـ Records (Java 16+)الـ Sealed Classes (Java 17+)11أنماط التصميم - الجزء الأول
مقدمة في أنماط التصميمنمط Singletonنمط Factoryنمط Builderنمط Observerنمط Strategy3خصائص الفئة والعضو الساكن
المتغيرات الخاصة بالكائن مقابل المتغيرات الساكنةالدوال الساكنةالكتل البرمجية الساكنةالثوابت (static final)ملخص - العداد والأدوات المساعدة6الواجهات (Interfaces) والأصناف المجردة (Abstract Classes)
مقدمة في الواجهات (Interfaces)تنفيذ الواجهات (Interfaces)تنفيذ واجهات متعددةالـ Default و Static في الواجهاتالأصناف المجردة مقابل الواجهاتالواجهات الوظيفية (Functional Interfaces)مراجعة - نظام الدفع9الأنواع العامة (Generics)
مقدمة في الأنواع العامةالأصناف العامة (Generic Classes)الدوال العامة (Generic Methods)معاملات الأنواع المقيدةالرموز البديلة (?, extends, super)مراجعة - الحاويات العامة12أنماط التصميم - الجزء الثاني
نمط الأمرنمط المحولنمط المزيننمط طريقة القالبنمط الحالةنمط التركيبنمط المكرر