معلومات عامة عن المقاولين
Конструктор
هي بنية مشابهة للطريقة، والغرض منها هو إنشاء مثيل للفئة. خصائص المصمم :
- يجب أن يتطابق اسم المنشئ مع اسم الفئة (وفقًا للاتفاقية، يتم كتابة الحرف الأول بحرف كبير، وعادةً ما يكون اسمًا)؛
- هناك منشئ في أي فئة. حتى لو لم تكتب واحدًا، فسيقوم مترجم Java بإنشاء مُنشئ افتراضي، والذي سيكون فارغًا ولن يفعل شيئًا سوى استدعاء مُنشئ الطبقة الفائقة.
- يشبه المنشئ الطريقة، لكنه ليس طريقة، ولا يعتبر حتى عضوًا في الفصل. لذلك، لا يمكن توريثها أو تجاوزها في فئة فرعية؛
- لا يتم توريث البنائين.
- يمكن أن يكون هناك العديد من المنشئين في الفصل الدراسي. في هذه الحالة، يقال أن المنشئين مثقلون؛
- إذا لم تحدد الفئة مُنشئًا، فسيقوم المترجم تلقائيًا بإضافة مُنشئ بدون معلمات إلى الكود؛
- لا يحتوي المُنشئ على نوع إرجاع؛ ولا يمكن حتى أن يكون نوعًا
void
؛ إذا تم إرجاع نوع void
، فإنه لم يعد مُنشئًا بل طريقة، على الرغم من تطابقه مع اسم الفئة.
- يُسمح بالمشغل في المُنشئ
return
، ولكنه فارغ فقط، دون أي قيمة إرجاع؛
- يسمح المنشئ باستخدام معدّلات الوصول؛ يمكنك تعيين أحد المعدلات: أو
public
أو protected
بدون private
معدّل.
- لا يمكن للمنشئ أن يحتوي على المعدلات أو
abstract
, أو ;final
native
static
synchronized
- تشير الكلمة الأساسية
this
إلى منشئ آخر في نفس الفئة. إذا تم استخدامه، يجب أن يكون الاستدعاء به هو السطر الأول من المُنشئ؛
- الكلمة الأساسية
super
تستدعي منشئ الفئة الأصل. إذا تم استخدامه، يجب أن يكون المرجع إليه هو السطر الأول من المنشئ؛
- إذا لم يقم المُنشئ باستدعاء مُنشئ
super
فئة السلف (مع أو بدون وسيطات)، يضيف المترجم تلقائيًا رمزًا لاستدعاء مُنشئ فئة السلف بدون وسيطات؛
المنشئ الافتراضي
هناك منشئ في أي فئة. حتى لو لم تكتب واحدًا، فسيقوم مترجم Java بإنشاء مُنشئ افتراضي. هذا المنشئ فارغ ولا يفعل شيئًا سوى استدعاء مُنشئ الطبقة الفائقة. أولئك. إذا كتبت:
public class Example {}
فهذا يعادل الكتابة:
public class Example
{
Example()
{
super;
}
}
في هذه الحالة، لم يتم تحديد فئة السلف بشكل صريح، وافتراضيًا، ترث جميع فئات Java الفئة،
Object
لذلك يُطلق على مُنشئ الفئة اسم
Object
. إذا قامت فئة ما بتعريف مُنشئ ذي معلمات، ولكن لا يوجد مُنشئ بدون معلمات محمّل بشكل زائد، فإن استدعاء المُنشئ بدون معلمات يعد خطأً. ومع ذلك، في Java منذ الإصدار 1.5، من الممكن استخدام المُنشئات ذات الوسائط المتغيرة الطول. وإذا كان هناك مُنشئ يحتوي على وسيطة ذات طول متغير، فلن يكون استدعاء المُنشئ الافتراضي خطأً. لن يحدث ذلك لأن وسيطة الطول المتغير يمكن أن تكون فارغة. على سبيل المثال، لن يتم تجميع المثال التالي، ولكن إذا قمت بإلغاء تعليق المنشئ باستخدام وسيطة متغيرة الطول، فسيتم تجميعه وتشغيله بنجاح وينتج عنه تشغيل سطر من التعليمات البرمجية
DefaultDemo dd = new DefaultDemo()
؛ سيتم استدعاء المنشئ
DefaultDemo(int ... v)
. وبطبيعة الحال، في هذه الحالة من الضروري استخدام JSDK 1.5. ملف
DefaultDemo.java
class DefaultDemo
{
DefaultDemo(String s)
{
System.out.print("DefaultDemo(String)");
}
public static void main(String args[])
{
DefaultDemo dd = new DefaultDemo();
}
}
نتيجة إخراج البرنامج مع المنشئ بدون تعليق:
DefaultDemo(int ...)
ومع ذلك، في الحالة الشائعة حيث لا تحدد الفئة أي مُنشئ على الإطلاق، سيكون استدعاء المُنشئ الافتراضي (بدون معلمات) ضروريًا، نظرًا لأن استبدال المُنشئ الافتراضي يحدث تلقائيًا.
إنشاء الكائنات والبنائين
عند إنشاء كائن، يتم تنفيذ الإجراءات التالية بالتتابع:
- يتم البحث عن فئة الكائن بين الفئات المستخدمة بالفعل في البرنامج. إذا لم يكن موجودا، فسيتم البحث عنه في جميع الفهارس والمكتبات المتاحة للبرنامج. بمجرد اكتشاف فئة في دليل أو مكتبة، يتم إنشاء الحقول الثابتة للفئة وتهيئتها. أولئك. لكل فئة، تتم تهيئة الحقول الثابتة مرة واحدة فقط.
- يتم تخصيص الذاكرة للكائن.
- يتم الآن تهيئة حقول الفصل.
- يتم تنفيذ منشئ الفئة.
- يتم إنشاء رابط للكائن الذي تم إنشاؤه وتهيئته. هذا المرجع هو قيمة التعبير الذي يقوم بإنشاء الكائن. يمكن أيضًا إنشاء كائن عن طريق استدعاء أسلوب
newInstance()
الفصل java.lang.Class
. في هذه الحالة، يتم استخدام مُنشئ بدون قائمة معلمات.
التحميل الزائد للمصممين
يمكن أن يكون للمنشئين من نفس الفئة نفس الاسم وتوقيع مختلف. تسمى هذه الخاصية بالجمع أو التحميل الزائد. إذا كان الفصل يحتوي على مُنشئات متعددة، فهذا يعني أن التحميل الزائد للمنشئ موجود.
بناة المعلمة
توقيع المنشئ هو عدد المعلمات وأنواعها، بالإضافة إلى تسلسل أنواعها في قائمة معلمات المنشئ. لا يؤخذ في الاعتبار نوع الإرجاع. لا يقوم المُنشئ بإرجاع أية معلمات. يشرح هذا البيان، إلى حد ما، كيف تميز Java بين المنشئات أو الأساليب المحملة بشكل زائد. تميز Java الطرق المحملة بشكل زائد ليس من خلال نوع الإرجاع الخاص بها، ولكن من خلال عدد وأنواع وتسلسل أنواع معلمات الإدخال. لا يمكن للمنشئ حتى إرجاع النوع
void
، وإلا فإنه سيتحول إلى طريقة عادية، على الرغم من أنه يشبه اسم الفئة. يوضح المثال التالي هذا. ملف
VoidDemo.java
class VoidDemo
{
VoidDemo()
{
System.out.println("Constructor");
}
void VoidDemo()
{
System.out.println("Method");
}
public static void main(String s[])
{
VoidDemo m = new VoidDemo();
}
}
ونتيجة لذلك، سيخرج البرنامج:
Constructor
يثبت هذا مرة أخرى أن المُنشئ هو طريقة بدون معلمات إرجاع. ومع ذلك، يمكن إعطاء المنشئ أحد المعدلات الثلاثة
public
،
private
أو
protected
. وسيبدو المثال الآن كما يلي: File
VoidDemo2.java
class VoidDemo2
{
public VoidDemo2()
{
System.out.println("Constructor");
}
private void VoidDemo2()
{
System.out.println("Method");
}
public static void main(String s[])
{
VoidDemo2 m = new VoidDemo2();
}
}
يُسمح بكتابة عامل تشغيل في المُنشئ
return
، ولكن فقط عامل تشغيل فارغ، دون أي قيمة إرجاع. ملف
ReturnDemo.java
class ReturnDemo
{
public ReturnDemo()
{
System.out.println("Constructor");
return;
}
public static void main(String s[])
{
ReturnDemo r = new ReturnDemo();
}
}
المنشئون ذوو معلمات باستخدام وسيطات ذات طول متغير
قدمت Java SDK 1.5 أداة طال انتظارها - وسائط متغيرة الطول للمنشئين والأساليب. في السابق، كانت تتم معالجة عدد متغير من المستندات بطريقتين غير مناسبتين. تم تصميم الأول منهم للتأكد من أن الحد الأقصى لعدد الوسائط يقتصر على عدد صغير ومعروف مسبقًا. في هذه الحالة، كان من الممكن إنشاء إصدارات مثقلة من الطريقة، واحدة لكل إصدار من قائمة الوسائط التي تم تمريرها إلى الطريقة. الطريقة الثانية مصممة لشيء غير معروف مسبقًا وعدد كبير من الوسائط. في هذه الحالة، تم وضع الوسائط في مصفوفة، وتم تمرير هذا المصفوفة إلى الطريقة. غالبًا ما يتم استخدام الوسائط ذات الطول المتغير في عمليات المعالجة اللاحقة مع التهيئة المتغيرة. من الملائم استبدال غياب بعض المنشئ أو وسيطات الطريقة المتوقعة بالقيم الافتراضية. وسيطة الطول المتغير عبارة عن مصفوفة، ويتم التعامل معها كمصفوفة. على سبيل المثال، منشئ فئة
Checking
ذات عدد متغير من الوسائط سيبدو كما يلي:
class Checking
{
public Checking(int ... n)
{
}
}
مجموعة الأحرف... تخبر المترجم أنه سيتم استخدام عدد متغير من الوسائط، وأنه سيتم تخزين هذه الوسائط في مصفوفة قيمتها المرجعية موجودة في المتغير n. يمكن استدعاء المنشئ بعدد مختلف من الوسائط، بما في ذلك عدم وجود أي وسائط على الإطلاق. يتم وضع الوسائط تلقائيًا في مصفوفة وتمريرها عبر n. إذا لم تكن هناك وسائط، يكون طول المصفوفة 0. ويمكن أن تتضمن قائمة المعلمات، إلى جانب الوسائط المتغيرة الطول، معلمات إلزامية أيضًا. في هذه الحالة، يجب أن تكون المعلمة التي تحتوي على عدد متغير من الوسائط هي الأخيرة في قائمة المعلمات. على سبيل المثال:
class Checking
{
public Checking(String s, int ... n)
{
}
}
هناك قيود واضحة للغاية تتعلق بعدد المعلمات ذات الطول المتغير. يجب أن يكون هناك معلمة واحدة فقط ذات طول متغير في قائمة المعلمات. بالنظر إلى معلمتين متغيرتي الطول، فمن المستحيل على المترجم تحديد أين تنتهي إحدى المعلمات وتبدأ الأخرى. على سبيل المثال:
class Checking
{
public Checking(String s, int ... n, double ... d)
{
}
}
على سبيل المثال، هناك أجهزة
Checking.java
قادرة على التعرف على لوحات أرقام السيارات وتذكر أرقام مربعات المنطقة التي زارتها كل سيارة خلال النهار. من الضروري الاختيار من بين إجمالي عدد السيارات المسجلة، تلك التي زارت خلال النهار مربعين معينين، على سبيل المثال 22 و15، وفقًا لخريطة المنطقة. ومن الطبيعي أن تتمكن السيارة من زيارة العديد من الساحات خلال النهار، أو ربما واحدة فقط. من الواضح أن عدد المربعات التي تمت زيارتها محدود بالسرعة المادية للسيارة. لنقم بإنشاء برنامج صغير حيث سيأخذ منشئ الفصل رقم السيارة كمعلمة إلزامية وعدد المربعات التي تمت زيارتها في المنطقة كوسيطات، والتي يمكن أن يكون عددها متغيرًا. سوف يتحقق المنشئ مما إذا كانت السيارة قد ظهرت في مربعين، وإذا ظهرت، قم بعرض رقمها على الشاشة.
تمرير المعلمات إلى المنشئ
هناك نوعان رئيسيان من المعلمات في لغات البرمجة:
- الأنواع الأساسية (الأوليات)؛
- المراجع إلى الكائنات.
يعني مصطلح الاستدعاء بالقيمة أن المُنشئ يتلقى القيمة التي تم تمريرها إليه بواسطة وحدة الاستدعاء. في المقابل، الاتصال حسب المرجع يعني أن المنشئ يتلقى عنوان المتغير من المتصل. تستخدم Java الاتصال حسب القيمة فقط. حسب قيمة المعلمة وقيمة رابط المعلمة. لا تستخدم Java الاتصال حسب المرجع للكائنات (على الرغم من أن العديد من المبرمجين ومؤلفي بعض الكتب يدعون ذلك). عند تمرير كائنات إلى Java،
لا يتم تمرير المعلمات حسب المرجع ، ولكن
من خلال قيمة مرجع الكائن ! في كلتا الحالتين، يتلقى المنشئ نسخًا من قيم جميع المعلمات. لا يمكن للمنشئ التعامل مع معلمات الإدخال الخاصة به:
- لا يمكن للمنشئ تغيير قيم معلمات الإدخال للأنواع الرئيسية (البدائية)؛
- لا يمكن للمنشئ تغيير مراجع معلمات الإدخال؛
- لا يمكن للمنشئ إعادة تعيين مراجع معلمات الإدخال إلى كائنات جديدة.
يمكن للمنشئ أن يفعل مع معلمات الإدخال الخاصة به:
- تغيير حالة الكائن الذي تم تمريره كمعلمة إدخال.
يوضح المثال التالي أنه في Java، يتم تمرير معلمات الإدخال إلى المُنشئ حسب القيمة المرجعية للكائن. يعكس هذا المثال أيضًا أن المنشئ لا يمكنه تغيير مراجع معلمات الإدخال، ولكنه في الواقع يغير مراجع نسخ معلمات الإدخال. ملف
Empoyee.java
class Employee
{
Employee(String x, String y)
{
String temp = x;
x = y;
y = temp;
}
public static void main(String args[])
{
String name1 = new String("Alice");
String name2 = new String("Mary");
Employee a = new Employee(name1, name2);
System.out.println("name1="+name1);
System.out.println("name2="+name2);
}
}
مخرجات البرنامج هي :
name1=Alice
name2=Mary
إذا استخدمت Java الاتصال حسب المرجع لتمرير الكائنات كمعلمات، فسيقوم المنشئ بتبديل
name1
و في هذا المثال
name2
. لن يقوم المُنشئ فعليًا بتبديل مراجع الكائنات المخزنة في
name1
والمتغيرات
name2
. يشير هذا إلى أنه تتم تهيئة معلمات المنشئ بنسخ من هذه المراجع. ثم يقوم المنشئ بتبديل النسخ. عندما يكمل المنشئ عمله، يتم تدمير المتغيرات x و y،
name1
وتستمر المتغيرات الأصلية
name2
في الإشارة إلى الكائنات السابقة.
تغيير المعلمات التي تم تمريرها إلى المنشئ.
لا يمكن للمنشئ تعديل المعلمات التي تم تمريرها للأنواع الأساسية. ومع ذلك، يمكن للمنشئ تعديل حالة الكائن الذي تم تمريره كمعلمة. على سبيل المثال، خذ بعين الاعتبار البرنامج التالي: File
Salary1.java
class Salary1
{
Salary1(int x)
{
x = x * 3;
System.out.println("x="+x);
}
public static void main(String args[])
{
int value = 1000;
Salary1 s1 = new Salary1(value);
System.out.println("value="+value);
}
}
مخرجات البرنامج هي :
x=3000
value=1000
من الواضح أن هذه الطريقة لن تغير معلمة النوع الرئيسي. ولذلك، بعد استدعاء المنشئ، تظل قيمة المتغير
value
مساوية لـ
1000
. في الأساس تحدث ثلاثة أشياء:
- تتم تهيئة المتغير
x
بنسخة من قيمة المعلمة value
(أي رقم 1000
).
- تضاعفت قيمة المتغير
x
ثلاث مرات - وهي الآن تساوي 3000
. ومع ذلك، تظل قيمة المتغير value
مساوية لـ 1000
.
- ينتهي المنشئ
x
ولم يعد المتغير مستخدمًا.
في المثال التالي، تمت مضاعفة راتب الموظف ثلاث مرات بنجاح لأنه تم تمرير قيمة مرجع الكائن كمعلمة للأسلوب. ملف
Salary2.java
class Salary2
{
int value = 1000;
Salary2()
{
}
Salary2(Salary2 x)
{
x.value = x.value * 3;
}
public static void main(String args[])
{
Salary2 s1 = new Salary2();
Salary2 s2 = new Salary2(s1);
System.out.println("s1.value=" +s1.value);
System.out.println("s2.value="+s2.value);
}
}
مخرجات البرنامج هي :
s1.value=3000
s2.value=1000
يتم استخدام قيمة مرجع الكائن كمعلمة. عند تنفيذ الخط
Salary2 s2 = new Salary2(s1)
; سيتم تمرير المنشئ
Salary2(Salary x)
قيمة مرجع إلى الكائن المتغير
s1
، وسيعمل المنشئ على مضاعفة الراتب ثلاث مرات
s1.value
، حيث أن النسخة
(Salary x)
التي تم إنشاؤها داخل المنشئ تشير إلى الكائن المتغير
s1
.
المنشئون المعلمات بواسطة البدائيين.
إذا كانت معلمات المُنشئ المحمل بشكل زائد تستخدم بدائية يمكن تضييقها (على سبيل المثال
int <- double
)، فمن الممكن استدعاء طريقة ذات قيمة ضيقة، على الرغم من عدم وجود طريقة مثقلة بمثل هذه المعلمة. على سبيل المثال: ملف
Primitive.java
class Primitive
{
Primitive(double d)
{
d = d + 10;
System.out.println("d="+d);
}
public static void main(String args[])
{
int i = 20;
Primitive s1 = new Primitive(i);
}
}
مخرجات البرنامج هي :
d=30.0
على الرغم من أن الفئة
Primitive
لا تحتوي على مُنشئ يحتوي على معلمة نوع
int
، إلا أن المنشئ الذي يحتوي على معلمة إدخال سيعمل
double
.
i
قبل استدعاء المنشئ، سيتم توسيع المتغير من نوع
int
إلى نوع
double
. الخيار المعاكس، عندما
i
يكون المتغير من النوع
double
، والمنشئ سيكون له معلمة فقط
int
، في هذه الحالة قد يؤدي إلى خطأ في الترجمة.
استدعاء المنشئ والمشغلnew
يتم استدعاء المنشئ دائمًا بواسطة المشغل
new
. عندما يتم استدعاء المُنشئ باستخدام عامل التشغيل
new
، يقوم المُنشئ دائمًا بإنشاء مرجع لكائن جديد. من المستحيل إجبار المُنشئ على تكوين مرجع لكائن موجود بالفعل بدلاً من مرجع لكائن جديد، إلا عن طريق استبدال الكائن الذي يتم إلغاء تسلسله. ومع العامل الجديد، بدلاً من الارتباط بكائن جديد، من المستحيل إنشاء رابط لكائن موجود بالفعل. على سبيل المثال: ملف
Salary3.java
class Salary3
{
int value = 1000;
Salary3()
{
}
Salary3(Salary3 x)
{
x.value = x.value * 3;
}
public static void main(String args[])
{
Salary3 s1 = new Salary3();
System.out.println("First object creation: "+s1.value);
Salary3 s2 = new Salary3(s1);
System.out.println("Second object creation: "+s2.value);
System.out.println("What's happend with first object?:"+s1.value);
Salary3 s3 = new Salary3(s1);
System.out.println("Third object creation: "+s3.value);
System.out.println("What's happend with first object?:"+s1.value);
}
}
مخرجات البرنامج هي :
First object creation: 1000
Second object creation: 1000
What's happend with first object?: 3000
Third object creation: 1000
What's happend with first object?: 9000
أولاً، باستخدام الخط
Salary3 s1 = new Salary3()
؛ يتم إنشاء كائن جديد. التالي، إذا كنت تستخدم الخط
Salary3 s2 = new Salary3(s1)
؛ أو سلاسل
Salary3 s3 = new Salary3(s1)
؛ سيكون من الممكن إنشاء رابط لكائن موجود بالفعل، ثم
s1.value s2.value
يقومون
s3.value
بتخزين نفس القيمة
1000
. في الواقع في السطر
Salary3 s2 = new Salary3(s1)
; سيتم إنشاء كائن جديد للمتغير
s2
وستتغير حالة الكائن للمتغير
s1
عن طريق تمرير قيمته المرجعية إلى الكائن في معلمة المنشئ. ويمكن التحقق من ذلك من خلال نتائج الإخراج. وعند تنفيذ الخط
Salary3 s3 = new Salary3(s1)
; سيتم إنشاء كائن جديد للمتغير
s3
وستتغير حالة الكائن للمتغير مرة أخرى
s1
.
المنشئون وكتل التهيئة، تسلسل الإجراءات عند استدعاء المنشئ
يسرد القسم
إنشاء كائن ومنشئات الإجراءات العامة التي يتم تنفيذها عند إنشاء كائن. من بينها عمليات تهيئة حقول الفئة والعمل على مُنشئ الفئة، والتي بدورها لها أيضًا ترتيب داخلي:
- تتم تهيئة جميع حقول البيانات إلى قيمها الافتراضية (0 أو خطأ أو فارغ).
- يتم تنفيذ كافة مُهيئات الحقول وكتل التهيئة بالترتيب المُدرج في إعلان الفصل.
- إذا تم استدعاء مُنشئ آخر في السطر الأول من المُنشئ، فسيتم تنفيذ المُنشئ المُستدعى.
- يتم تنفيذ جسد المنشئ.
يرتبط المنشئ بالتهيئة لأنه في Java توجد ثلاث طرق لتهيئة حقل في الفصل:
- تعيين قيمة في الإعلان؛
- تعيين القيم في كتلة التهيئة؛
- تعيين قيمته في المنشئ.
وبطبيعة الحال، تحتاج إلى تنظيم رمز التهيئة بحيث يكون من السهل فهمه. يتم إعطاء الفئة التالية كمثال:
class Initialization
{
int i;
short z = 10;
static int x;
static float y;
static
{
x = 2000;
y = 3.141;
}
Initialization()
{
System.out.println("i="+i);
System.out.println("z="+z);
z = 20;
System.out.println("z="+z);
}
}
في المثال أعلاه، تتم تهيئة المتغيرات بالترتيب التالي: تتم تهيئة المتغيرات الثابتة أولاً
x
بالقيم
y
الافتراضية. بعد ذلك، يتم تنفيذ كتلة التهيئة الثابتة. ثم تتم تهيئة المتغير
i
إلى القيمة الافتراضية وتتم تهيئة المتغير
z
. بعد ذلك، يبدأ المصمم في العمل. يجب ألا يعتمد استدعاء منشئي الفئة على الترتيب الذي يتم به إعلان الحقول. وهذا قد يؤدي إلى أخطاء.
البنائين والميراث
لا يتم توريث البنائين. على سبيل المثال:
public class Example
{
Example()
{
}
public void sayHi()
{
system.out.println("Hi");
}
}
public class SubClass extends Example
{
}
يرث الفصل
SubClass
تلقائيًا الطريقة
sayHi()
المحددة في الفصل الأصلي. وفي الوقت نفسه،
Example()
لا يرث منشئ الفئة الأصلية من قبل سليلها
SubClass
.
الكلمة الرئيسية this
في الصانعين
يتم استخدام المنشئين
this
للإشارة إلى منشئ آخر في نفس الفئة، ولكن مع قائمة مختلفة من المعلمات. إذا كان المنشئ يستخدم الكلمة الأساسية
this
، فيجب أن تكون في السطر الأول، وتجاهل هذه القاعدة سيؤدي إلى خطأ في المترجم. على سبيل المثال: ملف
ThisDemo.java
public class ThisDemo
{
String name;
ThisDemo(String s)
{
name = s;
System.out.println(name);
}
ThisDemo()
{
this("John");
}
public static void main(String args[])
{
ThisDemo td1 = new ThisDemo("Mary");
ThisDemo td2 = new ThisDemo();
}
}
مخرجات البرنامج هي :
Mary
John
في هذا المثال هناك نوعان من المنشئين. الأول يتلقى وسيطة سلسلة. الثاني لا يتلقى أي وسائط، فهو ببساطة يستدعي المنشئ الأول باستخدام الاسم الافتراضي "John". وبالتالي، يمكنك استخدام المنشئات لتهيئة قيم الحقول بشكل صريح وافتراضي، وهو أمر ضروري غالبًا في البرامج.
الكلمة الرئيسية super
في الصانعين
يتم استخدام المنشئين
super
لاستدعاء مُنشئ الطبقة الفائقة. إذا كان المُنشئ يستخدم
super
، فيجب أن يكون هذا الاستدعاء في السطر الأول، وإلا فسيقوم المترجم بإلقاء خطأ. فيما يلي مثال: ملف
SuperClassDemo.java
public class SuperClassDemo
{
SuperClassDemo()
{
}
}
class Child extends SuperClassDemo
{
Child()
{
super();
}
}
في هذا المثال البسيط، يحتوي المُنشئ
Child()
على استدعاء
super()
يُنشئ مثيلًا للفئة
SuperClassDemo
، بالإضافة إلى الفئة
Child
. نظرًا لأنه
super
يجب أن يكون البيان الأول الذي يتم تنفيذه في مُنشئ فئة فرعية، فإن هذا الترتيب هو نفسه دائمًا ولا يعتمد على ما إذا كان
super()
. إذا لم يتم استخدامه، فسيتم تنفيذ المُنشئ الافتراضي (بدون معلمات) لكل فئة فائقة، بدءًا من الفئة الأساسية، أولاً. يوضح البرنامج التالي متى يتم تنفيذ المنشئين. ملف
Call.java
class A
{
A()
{
System.out.println("Inside A constructor.");
}
}
class B extends A
{
B()
{
System.out.println("Inside B constructor.");
}
}
class C extends B
{
C()
{
System.out.println("Inside C constructor.");
}
}
class Call
{
public static void main(String args[])
{
C c = new C();
}
}
الإخراج من هذا البرنامج:
Inside A constructor.
Inside B constructor.
Inside C constructor.
يتم استدعاء المنشئين حسب ترتيب التبعية الطبقية. هذا منطقي. نظرًا لأن الفئة الفائقة ليس لديها معرفة بأي فئة فرعية، فإن أي تهيئة تحتاج إلى تنفيذها تكون منفصلة. إذا كان ذلك ممكنًا، فيجب أن يسبق أي تهيئة يتم إجراؤها بواسطة الفئة الفرعية. ولهذا السبب يجب أن يتم ذلك أولاً.
بناة قابلة للتخصيص
تعد آلية تحديد نوع وقت التشغيل أحد المبادئ الأساسية القوية للغة Java التي تنفذ تعدد الأشكال. ومع ذلك، فإن مثل هذه الآلية لا تحمي المطور من صب النوع غير المتوافق في بعض الحالات. الحالة الأكثر شيوعًا هي معالجة مجموعة من الكائنات، والتي تكون أنواعها المختلفة غير معروفة مسبقًا ويتم تحديدها في وقت التشغيل. نظرًا لأن الأخطاء المرتبطة بعدم توافق النوع لا يمكن أن تظهر إلا في مرحلة وقت التشغيل، فإن هذا يجعل من الصعب العثور عليها وإزالتها. يؤدي إدخال الأنواع المخصصة في Java 2 5.0 إلى نقل بعض هذه الأخطاء من وقت التشغيل إلى وقت الترجمة ويوفر بعض أمان النوع المفقود. ليست هناك حاجة لصب النوع الصريح عند الانتقال من نوع
Object
إلى نوع خرساني. يجب أن يؤخذ في الاعتبار أن أدوات تخصيص النوع تعمل فقط مع الكائنات ولا تنطبق على أنواع البيانات البدائية التي تقع خارج شجرة وراثة الفئة. باستخدام الأنواع المخصصة، يتم تنفيذ كافة عمليات الإرسال تلقائيًا وخلف الكواليس. يتيح لك هذا الحماية من عدم تطابق الكتابة وإعادة استخدام التعليمات البرمجية في كثير من الأحيان. يمكن استخدام الأنواع المخصصة في المنشئين. يمكن تخصيص المُنشئين حتى لو لم تكن فئتهم من النوع المخصص. على سبيل المثال:
class GenConstructor
{
private double val;
<T extends Number> GenConstructor(T arg)
{
val = arg.doubleValue();
}
void printValue()
{
System.out.println("val: "+val);
}
}
class GenConstructorDemo
{
public static void main(String args[])
{
GenConstructor gc1 = new GenConstructor(100);
GenConstructor gc2 = new GenConstructor(123.5F);
gc1.printValue();
gc2.printValue();
}
}
نظرًا لأن المنشئ
GenConstructor
يحدد معلمة نوع مخصصة يجب أن تكون فئة مشتقة من class
Number
، فيمكن استدعاؤها من أي منها
GO TO FULL VERSION