الرفع والخفض في الأنواع وعامل instanceof
الرفع والخفض في الأنواع وعامل instanceof
تتيح لك تعددية الأشكال (Polymorphism) كتابة كود يتعامل مع النوع الأب، بينما يكون الكائن الفعلي في وقت التشغيل من أي صنف فرعي. ولكي تفعل ذلك بصورة صحيحة، تحتاج إلى فهم عمليتين: الرفع في النوع (Upcasting) — أي التعامل مع كائن الصنف الفرعي باعتباره من النوع الأب — والخفض في النوع (Downcasting) — أي تحويله مجددًا إلى الصنف الفرعي المحدد. يُبقي عامل instanceof — وصيغة مطابقة الأنماط المُضافة في Java 16+ — هذه التحويلات آمنة.
الرفع في النوع — الاتجاه الآمن
يعني الرفع في النوع تخزين مرجع كائن من صنف فرعي في متغير من نوع الأب. تُجري Java هذا ضمنيًا لأنه آمن دائمًا: الـ Dog هو دائمًا Animal، ولن تضيع أي بيانات.
Animal a = new Dog("Rex")، النوع المُعلَن (وقت الترجمة) للمتغير a هو Animal، لكن النوع الفعلي في وقت التشغيل لا يزال Dog. تستجيب استدعاءات التوابع للنوع في وقت التشغيل (هذه هي تعددية الأشكال من الدرس السابق)، غير أن المترجم لا يسمح لك إلا بالاستدعاءات الموجودة في Animal. لذا فإن a.fetch() سيكون خطأ في وقت الترجمة — حتى لو كان الكائن فعلًا من نوع Dog.
الخفض في النوع — الاتجاه الصريح
يعني الخفض في النوع تحويل المرجع من النوع الأب مجددًا إلى نوع الصنف الفرعي المحدد. يجب أن تكتب التحويل صراحةً لأن المترجم لا يستطيع ضمان ذلك في وقت الترجمة. إذا أخطأت، رمى Java استثناء ClassCastException في وقت التشغيل.
ClassCastException. استخدم instanceof لتأمين كل عملية خفض.
التحقق من الأنواع بـ instanceof
يختبر عامل instanceof ما إذا كان كائن ما نسخةً من صنف معين (أو أي من أصنافه الفرعية). استخدمه لتأمين الخفض:
هذا النمط آمن لكنه مطوّل قليلًا: تتحقق ثم تُحوِّل وتنتهي بمتغير ثانٍ. قدّمت Java 16 طريقة أكثر إيجازًا.
مطابقة الأنماط لـ instanceof (Java 16+)
مع مطابقة الأنماط، يحدث التحقق والتحويل في تعبير واحد، وتربط Java النتيجة تلقائيًا بمتغير جديد:
المتغير d موجود فقط داخل كتلة if (وفقط حيث يمكن لـ Java إثبات نجاح الاختبار). يُزيل هذا فئةً كاملةً من أخطاء ClassCastException العَرَضية.
مثال عملي
تخيّل قائمة من كائنات Animal مختلطة. تريد استدعاء سلوك محدد لكل نوع:
if/else instanceof، فهذا غالبًا مؤشر على أن السلوك يجب أن يكون داخل تابع مُستبدَل. instanceof هو الأداة المناسبة حين تحتاج فعلًا إلى سلوك محدد بالنوع لا يمكن وضعه في الصنف الأب — مثلًا عند العمل مع أصناف طرف ثالث لا تستطيع تعديلها.
instanceof مع عمق التوارث
يُرجع instanceof قيمة true لصنف الكائن وكل أب في السلسلة الهرمية:
الخلاصة
- الرفع في النوع ضمني وآمن دائمًا — يمكن تخزين مرجع الصنف الفرعي في متغير من نوع الأب.
- الخفض في النوع يتطلب تحويلًا صريحًا وقد يفشل في وقت التشغيل إذا كان الكائن من النوع الخاطئ.
- استخدم
instanceofلتأمين كل عملية خفض وتجنبClassCastException. - تجمع مطابقة الأنماط لـ instanceof في Java 16+ بين الاختبار والتحويل في خطوة واحدة مع ربط متغير مكتوب النوع تلقائيًا.
- يُرجع
instanceofأيضًاtrueللأنواع الأصلية وليس للصنف المحدد فحسب.