الأربعاء، 17 أكتوبر 2012

المنهج toString لجافا

يتم تنفيذ المنهج toString في جافا بهيمنة المنهج toString الخاص بالفئة "Object". يتم استخدام  المنهج toString لجافا  عندما نكون في حاجة الى تمثيل بنوع سلسلة "string" للكائن. وهو معرف في الفئة Object. تم تجاوز هذا المنهج لتخصيص تمثيل نوع سلسلة "string" لـ Object. أدناه هو برنامج عرض استخدام المنهج جافا الافتراضي toString  لـ Object .



عند تشغيل البرنامج   ToStringDemo، الإخراج هو :

Object toString() method : PointCoordinates@119c082
PointCoordinates@119c082 testing
 


في المثال أعلاه عندما نحاول طباعة الكائن PointCoordinates ، فإنه يستدعي داخليا المنهج toString () للكائن بما اننا لم نتجاوز المنهج toString () لجافا . بما ان المثال السابق لا يوجد لديه المنهج toString فهو يستخدم المنهج الافتراضي toString الخاص بالكائن "Object". شكل المنهج الافتراضي toString للكائن موضح أدناه.

اسم فئة ، "@" ، ونسخة hashcode  للكائن بنظام العد السداسي عشر (Hexadecimal) و متسلسلة في نوع سلسلة "string" .
عادة يتم تطبيق المنهج الافتراضي hashCode للكائن عن طريق تحويل عنوان ذاكرة للكائن الى عدد صحيح.

أدناه هو مثال لنفس البرنامج يظهر تجاوز المنهج الافتراضي للكائن toString . المنهج toString () يجب أن يكون وصفي و يجب أن يغطي كافة محتويات الكائن.

عند تشغيل البرنامج   ToStringDemo2 ، الإخراج هو :

X=10 Y=10
X=10 Y=10 testing

الفئة StringBuffer لجافا

الفئة StringBuffer لجافا 

الفئة StringBuffer هي فئة قابلة للتغيير على عكس الفئة String  الغير قابلة للتغيير لكلا من القدرات وسلسلة الأحرف للفئة StringBuffer. يمكن تغيير StringBuffer بطريقة حيوية. وتُفضل سلسلة المخازن "String buffers" عندما يتعلق الأمر بتعديلات ثقيلة لسلاسل الأحرف (إلحاق، وإدراج، وحذف وتعديل وغيرها).
ويمكن الحصول على سلاسل "Strings" من مخازن  السلسلة "string buffers" . بما ان الفئة StringBuffer لم تتجاوز المنهج equals() من الفئة كائن "Object class" ، ينبغي تحويل محتويات مخازن  السلسلة "string buffers" الى الكائنات  سلسلة "String objects" للقيام بمقارنة السلسلة.
يتم طرح StringIndexOutOfBoundsException إذا كان المؤشر غير صالح عند استخدام مؤشر خطأ في التلاعب بمخازن  السلسلة "string buffers"

إنشاء StringBuffers

المشيد StringBuffer

Output
strBuf1 : Bob
strBuf2 capacity : 100
strBuf3 capacity : 16

وظائف StringBuffer

البرنامج التالي يوضح استخدام بعض من مناهج StringBuffer الأساسية مثل :


1. capacity()

إرجاع القدرة الحالية لمخزن السلسلة "string buffer"

2. length()

إرجاع طول (عدد الأحرف) مخزن السلسلة .

3. charAt(int index)

يتم إرجاع الحرف المحدد للتسلسل المتمثل حاليا في مخزن السلسلة "string buffer"، كما يتضح من الوسيطة "argument"  لــ "index".

4. setCharAt(int index, char ch)

يتم تعيين الحرف الموجود في index لمخزن السلسلة "string buffer"  الى ch

6. insert(int offset, char c)

يقوم بإدراج تمثيل سلسلة للوسيطة char في المخزن المؤقت للسلسلة "string buffer".
علما أن الفئة StringBuffer قد حصلت على أكثر من طاقتها من مناهج "insert" الذين يمكن استخدامهم بناءً على حاجة التطبيق.

7. delete(int start, int end)

يزيل أحرف في السلسلة الفرعية من هذا الفئة StringBuffer

8. replace(int start, int end, String str)

يستبدل أحرف في السلسلة الفرعية من هذا الفئة StringBuffer بأحرف في سلسلة المحدد.

9. reverse()

يتم استبدال تسلسل الأحرف الواردة في المخزن المؤقت للسلسلة "string buffer" بعكس التسلسل الاحرف.

10. append(String str)

تقوم بإلحاق السلسلة بالمخزن المؤقت للسلسلة.
علما أن الفئة StringBuffer قد حصلت على أكثر من طاقتها من مناهج "append" الذين يمكن استخدامهم بناءً على حاجة التطبيق.

11. setLength(int newLength)

يعين طول المخزن المؤقت للسلسلة.

Output
strBuf1 : Bobby
strBuf1 capacity : 21
strBuf2 capacity : 100
strBuf3 capacity : 16
strBuf1 length : 5
strBuf1 charAt 2 : b
strBuf1 after setCharAt 1 to t is : Btbby
strBuf1 toString() is : Btbby
strBuf3 when appended with a String : beginner-java-tutorial
strBuf3 when c is inserted at 1 : bceginner-java-tutorial
strBuf3 when c is deleted at 1 : b
Reversed strBuf3 : b
strBuf2 :

مقارنة سلسلة أغراض

مقارنة سلسلة أغراض "String"  لجافا  لتحديد المساواة 

يمكن ان تكون مقارنة سلسلة أغراض "String"  لجافا بطرق عديدة كما هو مبين أدناه. بالإعتمادا على نوع المقارنة لسلسلة جافا الذي تحتاجه ، سنستخدم.
* مشغل ==
* منهج equals
* منهج compareTo

مقارنة باستخدام المشغل == 

يستخدم المشغل == عندما يكون لدينا مقارنة مراجع لكائن سلسلة. إذا يتجه إثان من متغيرات السلسلة "String variables"  إلى نفس الكائن في الذاكرة ، فالمقارنة تعود بنعم "true". خلاف ذلك، فإن المقارنة ترجع بلا "false". علما أن المشغل '==' لا يقارن مضمون هذا النص في سلسلة الكائنات. فإنه يقارن فقط المراجع التي توجه اليهم السلسلتين. والبرنامج التالي سيقوم بطباعة "The strings are unequal" في الحالة الأولى، و "The strings are equal" في الحالة الثانية.


مقارنة باستخدام المنهج  equals

يستخدم المنهج  equals عندما نكون في حاجة لمقارنة محتوى النص الموجود في كائنات  سلسلة "String objects". هذا المنهج يقوم بإرجاع صحيحا "true" عندما يكون إثنان من كائنات سلسلة "String objects" يحملان نفس المضمون (أي في نفس القيمة). والبرنامج التالي يقوم بطباعة "The strings are unequal" في الحالة الأولى، و "The strings are equal" في الحالة الثانية.



مقارنة باستخدام المنهج compareTo

يستخدم المنهج compareTo عندما نحتاج لتحديد ترتيب السلاسل حسب الترتيب الأبجدي lexicographically. فإنه يقارن القيمة "char " بنفس الطريقة التي يقوم بها المنهج equals . المنهج  compareTo يقوم بإرجاع عدد صحيح سالب إذا كان الكائن سلسلة الأول يسبق السلسلة الثانية. و يقوم بإرجاع صفر اذا كانت السلسلتين الاتي يجري مقارنتهما متساويتين. يقوم بإرجاع عدد صحيح موجب إذا كان السلسلة كائن الأولى تلي السلسلة الثانية. والبرنامج التالي يقوم بطباعة "name2 follows name1" في الحالة الأولى، و "name1 follows name3" في الحالة الثانية.

الفئة سلسلة أغراض String Class لجافا

السلاسل أغراض "Strings" في جافا 

الفئة سلسلة أغراض "String" لجافا غير قابل للتغيير، سلاسل الأغراض "Strings" في جافا اذا تم إنشاؤهم وتهيئتهم فلا يمكن تغيرهم على نفس المرجع. الفئة java.lang.String هي نهائية وهو ما يعني لا فئة يمكن ان توسعها. الفئة java.lang.String تختلف عن بقية الفئات الأخرى ، فارق واحد هو أنه يمكن استخدام كائنات سلسلة أغراض "String" مع مشغلي "+=" و "+" للتسلسل.

منهجين مفيدين لكائنات سلسلة أغراض "String objects" هم equals( ) و substring( ). يستخدم المنهج equals( ) لاختبار ما إذا كان لدين سلسلتين  تحتويان على نفس القيمة. و يستخدم المنهج substring( ) للحصول على جزء محدد من سلسلة معيّنة.

فئة لإنشاء Java.lang.String

يمكن إنشاء سلسلة بسيطة باستخدام سلسلة حرفية المغلقة داخل علامات التنصيص كما هو مبين؛

بما ان السلسلة الحرفية هي مرجع، فيمكن التلاعب بها مثل أي مرجع لسلسلة أخرى. يمكن تعيين القيمة المرجعية لسلسلة حرفية كمرجع لسلسلة أخرى.

إذا كان إثنان أو أكثر من السلاسل لديهم نفس مجموعة الأحرف في نفس التسلسل فإنهما يشتركان في نفس المرجع في الذاكرة. أدناه توضيح لهذه الظاهرة.

في التعليمات البرمجية أعلاه كافة مراجع السلسلة str1 و str2 و str3 تدل على نفس الكائن سلسلة "String object" ، مع تهيئة سلسلة الحروف : “My name is bob”. ولكن السلاسل str4 و str5 تدل على كائنات سلسلة جديدة.
يمكن أن يتم إنشاء سلسلة الكائنات من صفائف بايت "arrays of bytes" أو صفائف من الأحرف "arrays of characters" ، أو مخازن سلسلة "string buffers". وهناك طريقة بسيطة لتحويل أي قيمة بدائية لتتمثل في سلسلة وهو وصلها بــسلسلة فارغة ("") ، باستخدام مشغل تسلسل السلسلة "string concatenation operator" (+).


Output 
byteStr :
charStr : abCD
buffStr : abcde

المنهج المهيمن في جافا

يتحقق المنهج المهيمن "Method Overriding" عندما تقوم فئة فرعية بإلغى المناهج الغير ثابت المعرفة في الفئة الفائقة، وبعد ذلك تنفيذ المنهج الجديد في الفئة الفرعية التي يُتِم تنفيذها.
تعريف المنهج الجديد يجب ان يكون له نفس توقيع الفئة (أي اسم المنهج والمعلمات "parameters") ، ونوع الإرجاع "return type". ويتم اختيار المعلمات "parameters" و نوع الإرجاع "return type" فقط كمعايير لمطابقة  توقيع الفئة. فإذا كان للفئة الفرعية معلمات المنهج على النحو النهائي "final" فهو لا يهم بالنسبة لسيناريوهات المنهج المهيمن فيبق صحيحا. التعريف الجديدة للمنهج لا يضييق على إمكانية الوصول للمنهج، ولكن من الممكن توسيعها. التعريف الجديد للمنهج فقط تحديد جميع أو لا شيء ، أومجموعة فرعية من الفئات الستثنات (بما في ذلك الفئات الفرعية الخاصة بهم) المحدد في فقرة  "throws" للفئة المهيمنة الموجودة في فئة الفائقة
برنامج لشرح المفاهيم المختلفة للمنهج المهيمن في جافا


Output 

OverridingClass.method1()

SuperClassWithDifferentMethods.method2()
OverridingClass.method5()
OverridingClass.method6()
OverridingClass.method7()
OverridingClass.method8()

oc1.field1 : 30
oc1.field2 : 40
sc3.field1 : 10
sc3.field2 : 20
SuperClassWithDifferentMethods.method5()
SuperClassWithDifferentMethods.method5()
OverridingClass.method1()

تعريفات المنهج الجديد OverridingClass في الفئة الفرعية لها نفس التوقيع و نوع الإرجاع "return type" متل الفئة الفائقة SuperClassWithDifferentMethods . المنهج المهيمن الجديد method6 يحدد مجموعة من الاستثناءات (CustomException). تعريف المنهج المهيمن الجديد method7 يوسع إمكانية وصول الخاص "private" إلى العام "public". و المنهج المهيمن method8 يعلن المعلمة "parameter" على اساس نهائية "final"، وهي ليست جزءا من توقيع المنهج و هذا المنهج المهيمن يعمل جيدا.  المنهج الثابت "static method" لا يمكن تجاوزه ليكون مثيل لمنهج غير ثابتة  كما هو موضح في الإعلان عن المنهج المهيمن للمنهج method9. المنهج الثابتة "static method" هو فئة محددة وليس جزءا من أي كائن، في حين يتم استدعاء المناهج المهيمن بالنيابة عن الكائنات من الفئة الفرعية. لا توجد مثل هذه القيود على الحقول، وبالنسبة للحقول فقط أسماء الحقول هي المطلوبة. و لا يمكن تجاوز المنهج النهائي "final method" ، ومحاولة هذا الأمر سيؤدي إلى خطأ في وقت التحويل البرمجي. فالمنهج الخاص "private method" لا يمكن الوصول إليه من خارج الفئة التي تم تعريفه فيها ، وبالتالي ، لا يمكن للفئة الفرعية تجاوزه.
يجب على الفئة الفرعية استخدام الكلمة الأساسية "super" من أجل استدعاء المنهج الذي تم تجاوزه "overridden method" من الفئة المتفوقة. و لا يمكن لفئة فرعية تجاوز حقول الفئة الفائقة، ولكن يمكنها إخفائهم. يمكن للتعليمات البرمجية في فئة فرعية استخدام الكلمة الأساسية "super" للوصول إلى الأعضاء "members" ، بما في ذلك الحقول المخفية.
ويجب ملاحظة الفرق بين استدعاء المناهج المثيلة "instance methods" في الكائن والوصول إلى حقول كائن. عندما يتم استدعاء منهج مثيل لكائن باستخدام مرجع ، فهي فئة الكائن الحالي و يشار اليها بالمرجع "reference" ، وليس نوع المرجع هو الذي يحدد تطبيقات المنهج  التي سيتم تنفيذها. عندما يكون حقل كائن قد تم الوصول إلىه  باستخدام مرجع، فهو نوع المرجع، وليس فئة الكائن الحالي المرموز له بالمرجع، و يحدد هذا أيّ حقل سيكون قابل للوصول. ويتجلى هذا في البرنامج أعلاه

الفئة المجردة و الواجهة لجافا

الفئة المجردة لجافا  Abstract Class in java  

تستخدم الفئات المجردة لجافا "Java Abstract classes" للإعلان عن الخصائص المشتركة للفئات الفرعية "subclasses". الفئة المجردة لا يمكن أن تكون فئة مثيل "Instance". لا يمكن استخدامها إلا بوصفها الفئة المتفوقة "superclass" للفئات الأخرى الاتي إمتددن من الفئة المجردة. يتم تعريف الفئات المجردة بالكلمة المجردة "abstract keyword". وتستخدم الفئات المجردة لتوفير قالب أو تصميم لفئات فرعية محددة أسفل شجرة الميراث "inheritance tree".


مثل أي فئة أخرى، يمكن لفئة مجردة أن تحتوي على حقول التي تصف الخصائص والأساليب التي تصف الإجراءات التي يمكن أن تؤديها الفئة. يمكن لفئة مجردة "abstract class" أن تشمل المناهج التي لا تحتوي على التنفيذ "implementation". وتسمى هذه بالمناهج التجريدية "abstract methods". يجب الإعلان نهاية  المنهج التجريدي بفاصلة منقوطة ";" "semicolon" بدلا من كتلة. إذا كانت الفئة  لديها أي منهج  مجرد "abstract methods"، سواء المعلنة أو الموروثة، فيجب أن تعلن الفئة كاملة كفئة مجردة. و تستخدم المناهج التجريدية "abstract methods" لتقديم نموذج للفئات التي ترث المنهج  المجرد "abstract methods".
لا يمكن أن يكون للفئات المجردة مثيل، ويجب أن يكونوا كفئات فرعية ، ويجب توفير التطبيقات الفعلية للمناهج التجريدية "abstract methods". و بطبيعة الحال يمكن ان يتم تجاوز أي تنفيذ محدد، من قبل فئات فرعية إضافية "subclasses". يجب أن يكون للكائن تنفيذ لجميع مناهجه. تحتاج إلى إنشاء فئة فرعية لتوفر تنفيذ للمنهج التجريدي "abstract method".

ويمكن لفئة مجردة تسمى بــ "Vehicle"  ان يتم تحديدها مجردة لتمثيل التجريد العام لوسيلة نقل "Vehicle"،كما ان خلق  مثيلات "instances" من الفئة لا يكون ذا مغزى.

مثال على فئة تسمى شكل "shape" تعتبر كفئة مجردة
يمكننا أيضا تنفيذ الفئة أشكال عامة "shapes" كفئة مجردة حتى نتمكن من رسم خطوط ودوائر ومثلثات الخ ، جميع الأشكال لها بعض الحقول المشتركة و المناهج ، ولكن لكل واحد منها ، بطبيعة الحال ،المزيد من الحقول و المناهج. الفئة مجردة تضمن بأن يكون لكل شكل نفس الخصائص الأساسية. ونقوم بإعلان هذه الفئة مجردة لأنه لا يوجد شيء يمثل شكل عام. يمكن أن يكون هناك فقط الأشكال الملموسة مثل مربعات مثلثات ودوائر الخ




Output 
point: 0, 0

لاحظ أنه ، من أجل إنشاء كائن نقطة "Point" ، ففئتها لا يمكن أن تكون مجردة. هذا يعني أن كل المناهج المجردة للفئة شكل "Shape" يجب أن تنفذ من قبل الفئة نقطة "Point".


يجب أن تُعرِف الفئة الفرعية التنفيذ لكل منهج تجريدي "abstract method" للفئة المتفوقة المجردة ، أو الفئة الفرعية نفسها سوف تكون أيضا مجردة. وبالمثل يمكن أن يتم إنشاء كائنات أخرى باستخدام الشكل العام للفئة التجريدية.
العيب الكبير في استخدام الفئات المجردة هو عدم الفدرة على استخدام وراثة متعددة. بمعنى، عندما تمتد فئة من فئة مجردة، فإنه لا يمكنها تمديد أية فئة أخرى.

واجهة جافا Java Interface

في جافا، يتم حل مشكلة الوراثة "inheritance" المتعددة بإستعمال بناء قوي يسمى الواجهات "interfaces". ويمكن استخدام واجهة لتحديد القالب العام "generic template" ومن ثم فئة مجردة أو أكثر لتحديد  التطبيقات جزئية للواجهة. الواجهات تحدد فقط  الإعلان عن المنهج "method" (العام  و الضمني  و المجردة "implicitly public and abstract")، ويمكن أن تحتوي فقط على الحقول (التي هي ضمنية  ، العامة ، نهائية ، ثابتة "implicitly public static final"). تعريف الواجهة يبدأ مع  الكلمة الرئيسية واجهة "interface".  واجهة  لفئة مجردة مثل هذه لا يمكن إنشاء مثيل لها "instantiated".

الوراثة المتعددة "Multiple Inheritance" يسمح بها عند تمديد  الواجهات. واجهة واحدة يمكن أن تمتد الى واجهة  أو أكثر. جافا لا تدعم الوراثة متعددة "Multiple Inheritance" ، ولكنها تسمح لك بتمديد "extend" فئة واحدة وتنفيذ العديد من الواجهات.

إذا كانت الفئة التي تُطبق الواجهة لا تُعَرِّفْ جميع المناهج للواجهة، فيجب أن يتم إعلانها مجردة و تعريفات المناهج يجب ان توفيرها الفئة فرعية الاتي يمتددن من الفئة مجردة.

المثال 1 : فيما يلي مثال لواجهة بإسم شكل "interface"


يوجد أدناه الفئة نقطة "Point class" التي تطبق الواجهة الشكل "Shape interface".




على نحو مماثل، يمكن إنشاء الكائنات شكل الأخرى بإستعمال واجهة برمجة "interface programming" عن طريق تنفيذ واجهة شكل عامة .

مثال 2 : وفيما يلي برنامج لواجهات جافا "java interfaces program" يعرض قوة برمجة الواجهة "interface programming" لجافا

القائمة أدناه تضهر لنا 2 من الواجهات و 4 فئات  واحدة منهم فئة مجردة.
ملاحظة : المنهج toString في الفئة A1 هو نسخة تجاوزناها للمنهج الذي تم تحديده في فئة تسمى كائن "Object". الفئات B1 و C1 تلبي متطلبات عقد الواجهة. ولكن بما أن الفئة D1 لا  تقوم بتعريف كافة المناهج لتطبيق الواجهة I2 ، فإن الفئة D1  أعلنت مجردة.

أيضا ،
تُنتج "i1.methodI2" خطأ في عملية التحويل البرمجي "compilation" لأن هذا المنهج لم يعلن في I1 أو أي واحدة من الواجهات الفائقة لها هذا إذا كانت موجودة. بالتالي المسبل او ما يسمى بالداونكسة "downcast" لمرجعية الواجهة I1 يحل المشكلة كما تظهر في البرنامج. المشكلة نفسها تنطبق على "i1.methodA1" ، و تحل ايضا عن طريق المسبل او ما يسمى بالداونكسة "downcast".

عندما نستدعي المنهج toString () الذي هو منهج للفئة كائن "Object"، لا يبدو أن هناك أي مشكلة باعتبار أن كل واجهة أو فئة تمتد من كائن "Object" و أي فئة يمكن ان تتجاوز toString () الافتراضي لتتناسب مع احتياجات التطبيق الخاص بك. ((C1) O1). methodI1 () لها تحويل برمجي ناجح ، ولكن يُنْتِجْ ClassCastException في وقت التشغيل "runtime". هذا لأن B1 ليس لديها أي علاقة مع C1 إلا أنهم "الأشقاء". لا يمكنك قولبة الأشقاء واحدا في الآخر.

عندما يتم استدعاء منهج واجهة معينة على مرجع معين ، السلوك الذي سوف ينتج سيكون مناسب للفئة التي منها تم إنشاء هذا الكائن المعينة. هذا هو  تعدد أشكال وقت التشغيل "runtime polymorphism" استنادا إلى الواجهات و هيمنة المناهج.




Output 

I am in methodI1 of class B1

I am in methodI2 of class B1

I am in methodI1 of class B1

I am in methodI2 of class B1

var2 : I am in methodA1 of class A1
var3 : I am in methodA1 of class A1
var4 : toString() method of class A1
var5 : toString() method of class A1
var6 : C1@190d11
I am in methodI1 of class B1
I am in methodI1 of class B1
I am in methodI1 of class B1

تلبيس او قولبة كائن جافا

عملية التلبيس أو القولبة Typecast or typecasting:


تحويل النوع في مجال برمجة الكمبيوتر، هو عملية أو نتيجة لتغيير نوعية البيانات لكيان من نوعية إلى نوعية أخرى ، و بمعنى اخر تغيير نوع البيانات من نوع إلي نوع اخر في وقت التحويل البرمجي بدون التقييد بنوع معين وبدون التغيير في قيمتها إلا في حالات معينة فقط.
في عملية تلبيس او قولبة كائن جافا (typecasting) يمكن لمرجع كائن ان يتم تلبيسه او قولبته  في مرجع كائن آخر.
التلبيس او القولبة يمكن أن تكون  للفئة نفسها  أولأحد الفئات الفرعية، أو الفئة المتفوقة أو الواجهات.
يوجد قواعد لوقت التحويل البرمجي "compile-time"  و قواعد لوقت التشغيل "runtime"  لعملية التلبيس او القولبة "casting"  في جافا.


كيف نقوم بتلبيس او بمعنى آخر قولبة كائنات بواسطة فئة ديناميكيا تم تحميلها؟


قولبة مراجع الكائنات يعتمد على العلاقة بين الفئات المعنية في نفسه التسلسل الهرمي .
أي مرجع لكائن يمكن أن يسند الى مرجع لمتغير من نوع كائن، وذلك لأن فئة الكائن هي الفئة المتفوقة لكل فئات جافا.

يمكن أن يكون هناك اثنين من سيناريوهات جافا للقولبة 

  • Upcasting   آب كاستينق
  • Downcasting   داون كاستينق

عندما نقولب مرجع على امتداد التسلسل الهرمي انطلاقا من  الطبقة الجذرية في اتجاه أحد الفئات الفرعية، يسمى داونكاست. عندما نقولب مرجع على امتداد التسلسل الهرمي انطلاقا من أحد الفئات الفرعية  في اتجاه الطبقة الجذرية ، يسمى آبكاست. لا نحتاج إلى استخدام مشغل القولبة في هذه الحالة.

قواعد وقت التحويل البرمجي "compile-time"  موجودة لإلتقاط محاولات القولبة في الحالات الغير ممكنة. يحدث هذا عندما نحاول قولبة الكائنات الغير مترابطة تماما (وهذه ليست علاقات لفئة  فرعية أو لفئة  من الدرجة الاولى أو لواجهة). عند وقت التشغيل يتم طرح ClassCastException  إذا كان الكائن الذي سيتم قولبته غير متوافق مع النوع الجديد الذي سيتم القولبة إليه.

أدناه هو مثال يظهر متى يمكن حدوث ClassCastException  أثناء قولبة  الكائن "object casting"



قولبة مراجع الكائن "Object References": قولبة ضمنية باستخدام المحول البرمجي "Compiler" 


بشكل عام القولبة الضمنية تتم عندما يتم تعيين مرجع كائن "Object reference" (قولب أو تلبيس) إلى :

  • مرجع المتغير "reference variable" الذي لهو نفس نوع الفئة التي تم إنشاء الكائن منها.
  • الكائن كفئة كائن "Object  Class" هي الفئة الفائقة "super class" لكل فئة.
  • مرجع المتغير "reference variable" من نوع الفئة الفائقة "super class" للفئة  التي تم إنشاء الكائن منها.
  • مرجع المتغير "reference variable" من نوع واجهة  "interface"  التي تم تنفيذها "implemented"  من قبل الفئة  التي تم إنشاء الكائن منها.
  • مرجع المتغير "reference variable" من نوع واجهة  "interface"  التي تم تنفيذها "implemented"  من قبل الفئة الفائقة "super class" للفئة  التي تم إنشاء الكائن منها.

ليكن لدينا  واجهة "interface" إسمها وسيلة نقل "Vehicle"، و فئة فائقة "super class" إسمها  سيارة "Car"  و لها فئة فرعية "subclass" إسمها فورد "Ford". المثال التالي يوضح التحويل التلقائي من المراجع الكائن "object references" التي تمت معالجتها بواسطة المحول البرمجي "compiler"




ليكن "c" متغير من فئة السيارة "Car" و "f" من فئة  فورد "Ford" و "v" تكون مرجع الواجهة وسيلة نقل "vehicle ". يمكننا تعيين المرجع  "Ford" للمتغير "Car" :

مثال رقم 1








المحول البرمجي يعالج تلقائيا عملية التحويل و بما ان الأنواع متوافقة ( علاقة  بين فئة فرعية "subclass" و فئة فائقة "super class" ) ، أي نوع "Car" يمكن أن يشتمل  نوع "Ford" بما ان "Ford" هي سيارة "Car".


مثال رقم 2


التحويل الغير مشروع من النوع واجهة "interface type" إلى النوع فئة "class type"  سوف ينتج خطأ في عملية التحويل البرمجي و "v"هو مرجع  الواجهة "Vehicle v"
المحول البرمجي يعالج تلقائيا عملية التحويل و بما ان الأنواع متوافقة ( علاقة  بين فئة "class" و واجهة "interface" ) ، أي نوع "Car" يمكن أن يقولب "cast to" لنوع "Vehicle interface" بما ان "Car" هي  تنفيذ " implements" لــ "Vehicle Interface" (السيارة هي وسيلة نقل).

قولبة مراجع الكائن : القولبة الواضحة



أحيانا نقوم بقولبة واضحة "explicit cast" في جافا عندما تكون القولبة الضمنيا "implicit casts" لا تعمل أو ليست مفيدة لسيناريو معين. القولبة الواضحة "explicit cast" ليست سوى اسم النوع الجديد الموجود بين قوسين. مثل ما كان في السابق، بالنسة لفئة "Car" و الفئة "Ford"





كما ان لدينا الوظيفة  breakingSystem () الذي يأخذ المرجع "Car" (مرجع الفئة الفائقة "Superclass reference" ) كقيمة وسيطة للمدخلات "input parameter".
فإن المنهج يستدعي  carMethod () بغض النظر عن نوع الكائن (مرجع "Car" أو مرجع "Ford") وإذا كان هو كائن "Ford"، فإنه سيتم أيضا استدعاء fordMethod (). نستخدم المشغل instanceof لتحديد نوع الكائن في وقت التشغيل.


لإستدعاء fordMethod ()، العملية "(Ford) obj " تخبر المحول البرمجي "compiler" لعلاج الكائن المشار إليه بواسطة "obj"  كما لو أنه كائن "Ford". بدون القولبة فإن  المحول البرمجي "compiler" سوف يعطي رسالة خطأ تشير إلى أنه لا يمكن العثور  على fordMethod ()  في تعريف "Car".
يقدم البرنامج التالي توضيح استخدام مشغل القولبة "cast operator" مع المراجع.
ملاحظة : الفئات "Honda" و "Ford" يعتبروا أشقاء في التسلسل الهرمي للفئة. كل من الفئاتين هي فئة فرعية  "subclasse"من فئة "Car". كل من الفئة "Car" و الفئة "HeavyVehicle" إمتداد لفئة كائن "Object Class".
فإن أي فئة التي لا تمتد بشكل واضح من بعض فئات أخرى تمتد تلقائيا من كائن "object" افتراضيا. هذا الرمز ينشئ كائن مثيل لفئة "Ford"  ويقوم بتعيين مرجع الكائن لمرجع المتغير من نوع "Car".
ويسمح لهذا التعيين على اساس ان "Car" هي الفئة المتفوقة "superclass" لــ "Ford". من أجل استخدام مرجع من نوع فئة لاستدعاء المنهج "method"، يجب تعريف  المنهج "method" عند أو أعلى من هذه الفئة  في التسلسل الفئة الهرمي.
وبالتالي لا يمكن لكائن من فئة "Car" إستدعاء المنهج "method" موجودة في الفئة "Class Ford" ،  حيث أن المنهج  fordMethod غير موجود في الفئة "Car" أو اي واحد من الفئة المتفوقة "superclass" لها.
ويمكن بالتالي أن تحل هذه المشكلة بواسطة دونكاسة "downcast" بسيط  عن طريق قولبة مرجع الكائن  "Car" الى مرجع الفئة "Ford" كما فعلنا في البرنامج.
أيضا محاولة قولبة مرجع كائن الى مرجع الكائن الشقيق له تنتج ClassCastException في وقت التشغيل، على الرغم من ان عملية التحويل البرمجي تحدث من دون أي خطأ.





أحد عمليات القولبة الاكثر شيوعا التي يتم تنفيذها عند التعامل مع المجموعات، يمكنك قولبة مرجع كائن إلى  سلسلة الأغراض "String".



Output
Username : asdf
Username : asdf
Password : qwer



عامل التشغيل "instanceof" 


عامل التشغيل "instanceof" يسمى بمشغل مقارنة النوع ، يتيح لك تحديد ما إذا كان كائن ينتمي إلى فئة معينة، أو تنفيذ لواجهة معينة. فإنها تعود بصحيح "true" إذا كان الكائن هو مثيل لفئة "instance of the class" أو إذا كان الكائن تنفيذ لواجهة "implements the interface"، وإلا فإنها تعود بــ false.

أدناه هو مثال يوضح استخدام المشغل instanceof



Output
hV is an HeavyVehicle: true
T is an HeavyVehicle: true
hV is a Truck: false
hv2 is an HeavyVehicle: false



ملاحظة : hv2  ليس له مرجعية الى حد الان لكائن "HeavyVehicle" و ترجع instanceof  بــ false. كما أننا لا نستطيع استخدام المشغل instanceof مع الفئات الأشقاء.

الوراثة في جافا

الوراثة في جافا هي العلاقة بين الفئة المتفوقة و الفئة الفرعية التابعة لها. هذا يعني أنه يمكن استخدام كائن من الفئة فرعية "subclass" مثلما تستخدم اي كائن من الطبقة المتفوقة "superclass". آلية توريث الفئة في جافا تستخدم  لبناء فئات جديدة من الفئات الموجودة. العلاقة الوراثية هي إنتقالية : إذا كانت الفئة x تمتد من الفئة y، فإن الفئة z الممتدة من الفئة x سوف ترث أيضا من الفئة y.

على سبيل المثال يمكن لفئة سيارة "car" ان ترث بعض الخصائص من الفئة العامة لوسيلة نقل "vehicle". هنا نجد أن الفئة الأساسية هي الفئة وسيلة نقل "vehicle"  و الفئة الفرعية هي سيارة "car" التي هي أكثر تحديدا. يجب على الفئة الفرعية استخدام المصطلح "extends" للإشتقاق من الفئة فائقة  التي يجب أن يكون مكتوب في الرأسية الخاصة بتعريف الفئة الفرعية. ترث الفئة فرعية أعضاء من الفئة المتفوقة و هذا يعزز بالتالي إعادة استخدام التعليمات البرمجية. ويمكن للفئة الفرعية نفسها إضافة خصائص و تصرفات خاص بها. الفئة java.lang.Object دائما تكون في أعلى هرم الميراث لأي فئة .


Output 

Volume is : 1000.0

width of MatchBox 1 is 10.0
height of MatchBox 1 is 10.0
depth of MatchBox 1 is 10.0
weight of MatchBox 1 is 10.0
ما هو الغير ممكن عند استخدام توريث الفئة لجافا؟

1. الأعضاء الخاصين "Private members" للطبقة المتفوقة ليسوا قابلين للتوريث من قبل الفئة الفرعية، و لا يمكن الوصول إليهم إلا بشكل غير مباشر.
2. الأعضاء الذين لهم إمكانية الوصول الافتراضي في الفئة المتفوقة هم أيضا ليسوا قابلين للتوريث من قبل الفئات الفرعية لواجهات اخرى ، وهؤلاء الأعضاء لا يمكن الوصول إليهم إلا بأسمائهم البسيطة في الفئات الفرعية ضمن نفس الواجهة و نفس الفئة المتفوقة.
3. بما ان المنشؤون "constructors" وكتل المهيئ "initializer blocks" ليسوا أعضاء في الفئة ، فهم غير  قابلين للتوريث من قبل الفئة الفرعية.
4. فئة فرعية يمكنها فقط تمديد فئة فائقة واحدة


Output 

Constructor of the Super class called

Car number: 10
No of Tyres: 5
accessories: true
Brand: X
Number of Vehicles: 1

الكلمات "this" و "super" 


هاذين الكلمتين الأساسيتين ، "this" و "super" سيقومان بمساعدتك في اسم الحقل أو اسم المنهج الذي تريده. وباستخدام "this" و "super" لديك السيطرة الكاملة على امكانية استدعاء الحقل أو المنهج الموجود في نفس الفئة أو لإستدعائه من الفئة المتفوقة مباشرتا. يتم استخدام الكلمة "this"  كمرجع للكائن الحالي الذي هو مثيل للفئة الحالية. و تستخدم الكلمة "super"  أيضا كمراجع للكائن الحالي، ولكن كما مثيل للفئة الفائقة للفئة الحالية.

المرجع "this" للكائن الحالي هو مفيد في الحالات التي يكون فيها المتغير المحلي أخفى أو ظلل حقل بنفس الاسم. إذا كان المنهج يحتاج إلى تمرير الكائن الحالي إلى منهج آخر ، يمكن له أن يفعل ذلك باستخدام هذا المرجع. ملاحظة أن المرجع "this" لا يمكن أن يكون قد تم استخدامه في سياق ثابت ، كما لم يتم تنفيذ التعليمات البرمجية ثابتة في سياق أي كائن.


Output 

Volume is : 1000.0

width of MatchBox 1 is 10.0
height of MatchBox 1 is 10.0
depth of MatchBox 1 is 10.0
weight of MatchBox 1 is 10.0

التسلسل في جافا

مقدمة لتسلسل الكائن "Object Serialization"


يتم استخدام تسلسل الكائن "Object Serialization" في جافا  لتمرير أو بمعنى آخر تحويل كائنات جافا "Java objects" إلى ملف أو قاعدة بيانات أو عملية  أو شبكة أو أي نظام آخر. التسلسل يسوي الكائنات إلى وحدات البايت المتدفقة "stream of bytes" مرتبة أو متسلسلة. ويمكن بعد ذلك لوحدات البايت المتدفقة "stream of bytes" أن تُقرأ في وقت لاحق، أو في بيئة أخرى، لإعادتها الى الكائنات الأصلية.
تسلسل جافا لا يمكن أن يتم لحقول عابرة أو ثابتة. بالمناسبة الحقل العابر "field transient" يمنع " object state " من ان يتم كتابتها في التدفق "stream" و من استعادتها عند عملية إلغاء التسلسل "deserialization". جافا يقدم فئات لدعم كتابة الكائنات في التدفق "stream" و استعادة الكائنات من التدفق "stream". يمكن فقط للكائنات التي تدعم الواجهة  java.io.Serializable  أو الواجهة  java.io.Externalizable  الكتابة في التدفق "stream".

الواجهة العامة Serializable


الواجهة Serializable ليس لديها مناهج أو حقول. (واجهة ماركر)
فقط كائنات الفئات التي تقوم بتنفيذ واجهة java.io.Serializable يمكنها التسلسل أو فك التسلسل

الحقول العابرة "Transient Fields" والتسلسل في جافا "Java Serialization" 


الكلمة الأساسية العابرة "transient keyword" هي تعديل يُطبق على المتغيرات المثيلة "instance variables" في الفئة. وهي تحدد أن المتغير ليست جزءا من الحالة "state" المستمرة للكائن، وبالتالي لن يتم حفظها خلال التسلسل.
يمكنك استخدام الكلمة العابرة لوصف المتغيرات المؤقتة ، أو المتغيرات التي تحتوي على المعلومات المحلية، مثل معرف العملية "process ID" أو مرور الزمن "time lapse".

الإدخال والإخراج لجداول كائن "Object Streams"


ObjectOutputStream هي فئة تدفق الإخراج الأولية التي تطبق الواجهة ObjectOutput لتسلسل الكائنات. ObjectInputStream هي فئة تدفق الإدخال الأولية التي تطبق الواجهة ObjectInput deserializing لفك التسلسل للكائنات.
هذه الجداول ذات المستوى العال مرطبة  بتدفق السلاسل ذات المستوى المنخفض ، مثل FileInputStream أو FileOutputStream.
الجداول ذات المستوى المنخفض "low-level streams" تقوم بمعالجة بايت من البيانات "bytes of data". المنهج writeObject يحفظ حالة الفئة عن طريق كتابة الحقول الفردية في ObjectOutputStream. يستخدم المنهج readObject لإلغاء تسلسل كائن من تدفق إدخال الكائن "object input stream".

الحالة 1 : فيما يلي مثال يوضح تسلسل الكائن في ملف


PersonDetails هي الفئة النوات التي تطبق الواجهة Serializable



GetPersonDetails هي الفئة التي تستخدم لإلغاء تسلسل الكائن من الملف (person.txt).




PersonPersist هي الفئة التي تستخدم لتسلسل الكائن في الملف (person.txt).


الحالة 2 : فيما يلي مثال يوضح تسلسل الكائن في  قاعدة البيانات


PersonDetails يبقى نفسه كما هو مبين أعلاه
GetPersonDetails يبقى نفسه كما هو مبين أعلاه

إنشاء جدول SerialTest


PersonPersist هي الفئة التي تستخدم لتسلسل الكائن في جدول قاعدة البيانات SerialTest .




الحالة 3 : فيما يلي مثال يوضح تسلسل الكائن في  قاعدة البيانات  باستخدام قاعدة التشفير 64


PersonDetails يبقى نفسه كما هو مبين أعلاه

GetPersonDetails يبقى نفسه كما هو مبين أعلاه

إنشاء جدول SerialTest


PersonPersist هي الفئة التي تستخدم لتسلسل الكائن في جدول قاعدة البيانات SerialTest



أدناه هو برنامج يبين تسلسل الكائن JButton إلى ملف و تدفق مصفوفة بايت "Byte Array Stream". كما في السابق من اجل تسلسل theobject يجب تطبيق الواجهة Serializable.

PersonDetails هي الفئة النوات التي تطبق الواجهة Serializable