لقد استخدمنا سابقًا الفئات لإنشاء أنواع جديدة، واستخدمنا الميراث لتسهيل عملية إنشاء الفئات. في هذه المحاضرة سوف أتعمق في الأنواع وأقدم مفهوم تعدد الأشكال.
فحص النوع
لا يمكن استخدام أي متغيرات ومراجع في Java إلا بعد تمرير تعريف النوع. لقد رأينا من قبل أن بيانات الكائن، وبيانات الفئة، ومعلمات الطريقة، وقيم إرجاع الطريقة، والمتغيرات التلقائية داخل الطرق كلها تحتاج إلى الإعلان عن أنواعها. Java هي لغة مكتوبة بقوة، والتي تتحقق من الأنواع. إذا استخدمنا النوع الخطأ، فسوف يسبب أخطاء.
النوع غير متطابق، الجاذبية غير صالحة
على سبيل المثال، في فئة الاختبار أدناه، نقوم بتعيين كائن فئة Cup إلى مرجع فئة aPerson:
public class Test{ public static void main(String[] args) { Human aPerson = new Cup(); }}class Human{ /** * buildor */ public Human(int h) { this.height = h; } /** * الوصول */ public int getHeight() { return this.height } /** * mutator */ public void GrowHeight(int h) { this.height = this.height + h } public int height;}class Cup { public void addWater(int w) { this.water = this.water + w } public void DrinkWater(int w) { this.water = this.water - w } public int water = 0 ;}
سوف يعود جافاك:
تم العثور على: Cuprequired: Human aPerson = new Cup(); خطأ ^1
تحويل النوع الأساسي
يمكن لـ Java إجراء تحويل النوع على متغيرات الأنواع الأساسية. الأنواع الأساسية المختلفة لها أطوال ونطاقات تخزين مختلفة. إذا قمنا بالتحويل من نوع عالي الدقة إلى نوع منخفض الدقة، مثل التحويل من float إلى int، فقد نفقد المعلومات. ويسمى مثل هذا التحويل تحويلا تضييقيا. في هذه الحالة، نحتاج إلى الإعلان بوضوح عن تحويل النوع، مثل:
اختبار الطبقة العامة { public static void main(String[] args) { int a = (int) 1.23; // تضييق التحويل System.out.println(a);
إذا قمنا بالتحويل من نوع منخفض الدقة إلى نوع عالي الدقة، فلا يوجد قلق بشأن فقدان المعلومات. ويسمى هذا التحول تحويلا آخذا في الاتساع. لا نحتاج إلى طلب تحويل النوع بشكل صريح، يمكن لـ Java القيام بذلك تلقائيًا:
اختبار الطبقة العامة { public static void main(String[] args) { int a = 3;
تحويل النوع الأساسي
upcast وتعدد الأشكال
في Java، يمكن أيضًا كتابة المراجع، ولكن هناك قيود.
يمكننا تحويل مرجع فئة مشتقة إلى مرجع الفئة الأساسية الخاصة بها، وهو ما يسمى التحويل الصاعد أو المريح. ترث فئة BrokenCup التالية من فئة Cup وتتجاوز طريقتي addWater() و DrinkWater() الأصلية في فئة Cup:
public class Test{ public static void main(String[] args) { Cup aCup aBrokenCup = new BrokenCup(); void addWater(int w) { this.water = this.water + w } public void DrinkWater(int w) { this.water = this.water - w; } Private int water = 0;} class BrokenCup Extends Cup{ public void addWater(int w) { System.out.println("shit, Broken cup"); public void DrinkWater(int w) { System.out. println("أوم...رقم...، لا يوجد ماء بالداخل" }}
نتائج تشغيل البرنامج:
القرف، كوب مكسور
كما ترون أعلاه، بدون أي تعليمات صريحة، نقوم بتعيين مرجع الفئة المشتقة aBrokenCup إلى مرجع الفئة الأساسية الخاص بها aCup. سيتم إجراء تحويل النوع تلقائيًا بواسطة Java.
قمنا بعد ذلك بتسمية طريقة addWater() الخاصة بـ aCup (والتي أعلنا أنها من النوع Cup). على الرغم من أن aCup هو مرجع من النوع Cup، إلا أنه في الواقع يستدعي طريقة addWater() الخاصة بـ BrokenCup! بمعنى آخر، حتى لو قمنا بإرخاء النوع المرجعي إلى فئته الأساسية من خلال البث الصاعد، فلا يزال بإمكان Java تحديد نوع الكائن نفسه بشكل صحيح واستدعاء الطريقة الصحيحة. يمكن لـ Java تحديد النوع الحقيقي للكائن بناءً على الوضع الحالي، وهذا ما يسمى تعدد الأشكال. تعدد الأشكال هو جانب مهم من وجوه المنحى.
تعدد الأشكال هو آلية تدعمها Java وهو أيضًا مفهوم مهم موجه للكائنات. وهذا يثير سؤالًا تصنيفيًا حول ما إذا كانت كائنات الفئة الفرعية في الواقع "هي" كائنات فئة أصلية. على سبيل المثال، يعتبر الطائر حيوانًا أيضًا؛ ويجب أن تكون السيارة أيضًا وسيلة نقل. تخبرنا Java أنه يمكن استخدام كائن فئة مشتقة ككائن فئة أساسية، وسوف تتعامل Java مع هذا الموقف بشكل صحيح.
على سبيل المثال، علاقة الميراث التالية:
يمكننا القول أننا نشرب الماء من الكوب. في الواقع، فإن المعنى المحدد لعمل مياه الشرب سوف يتغير بشكل كبير في الفئة المشتقة. على سبيل المثال، شرب الماء من خلال القشة وشرب الماء من كوب مكسور مختلفان تمامًا، على الرغم من أننا نتحدث جميعًا عن "مياه الشرب" بشكل مجرد. بالطبع، يمكننا البرمجة بشكل منفصل لكل فئة مشتقة واستدعاء طرق DrinkWater المختلفة. ومع ذلك، كمبرمجين، يمكننا برمجة كوب واستدعاء طريقة Cup's DrinkWater()، بغض النظر عن نوع الكوب المشتق من الكوب. ستستدعي Java الطريقة الصحيحة المقابلة، كما نرى في البرنامج أعلاه.
بالنظر إلى مثال أكثر وضوحًا، نضيف طريقة Drink() إلى فئة Human. تتلقى هذه الطريقة كائن cup وعددًا صحيحًا كمعلمات. تمثل الأعداد الصحيحة كمية الماء التي يجب شربها:
public class Test{ public static void main(String[] args) { Human Guest = new Human(); BrokenCup hisCup = new BrokenCup(); , int w) { aCup.drinkWater(w }});
نتائج تشغيل البرنامج:
القرف، لا يوجد ماء في الداخل
في تعريف Drink() للفئة البشرية، نطلب أن يكون المعامل الأول مرجعًا للنوع Cup. ولكن في التطبيق الفعلي (فئة الاختبار)، يتم استخدام كائن الفئة المشتقة من BrokenCup الخاص بـ Cup. يؤدي هذا في الواقع إلى رفع كأسه إلى فئة الكأس وتمريره إلى طريقة Drink(). في هذه الطريقة، قمنا بتسمية طريقة DrinkWater(). اكتشفت Java أن هذا الكائن كان في الواقع كائن BrokenCup، لذا فقد أطلق بالفعل على الطريقة المقابلة لـ BrokenCup.
مسبل
يمكننا إسقاط مرجع الفئة الأساسية إلى مرجع فئة مشتقة، ولكن الكائن المشار إليه بواسطة مرجع الفئة الأساسية هو بالفعل كائن الفئة المشتقة المراد إسقاطه. على سبيل المثال، يمكن تحويل hisCup أعلاه إلى مرجع فئة Cup، ثم تحويله إلى مرجع فئة BrokenCup.
نوع الكائن
في Java، جميع الفئات لديها في الواقع سلف وراثة مشترك، وهو فئة الكائن. توفر فئة الكائن بعض الأساليب، مثل toString (). يمكننا تجاوز هذه الأساليب في تعريف الفئة الخاصة بنا.
الكائن: الجد
يمكننا كتابة برنامج يقوم بتشغيل كائنات الكائن، وتمرير أي كائن إلى البرنامج من خلال البث.
سوف أتعمق في فئة الكائن لاحقًا.
(يعتمد تنفيذ تعدد الأشكال على دعم RTTI. وسأتناول المزيد من التفاصيل لاحقًا.)
تلخيص
تحويل النوع الأساسي
تعدد الأشكال
مسبل
هدف