Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

معامل الـ instanceof

جزء من قسم Object Oriented Programming في رحلة Java على Coddy — الدرس 31 من 87.

أظهر الدرس السابق أن عملية التحويل لأسفل (downcasting) يمكن أن تفشل بـ ClassCastException إذا لم يكن الكائن في الواقع من النوع الذي تقوم بالتحويل إليه. يقوم عامل instanceof بحل هذه المشكلة من خلال السماح لك بالتحقق من نوع الكائن قبل عملية التحويل.

الصيغة البرمجية بسيطة: object instanceof ClassName تُرجع true إذا كان الكائن نسخة من تلك الفئة (أو أي من فئاتها الفرعية):

Animal animal = new Dog();

if (animal instanceof Dog) {
    Dog dog = (Dog) animal;
    dog.bark();  // من الآمن استدعاء الأساليب (methods) الخاصة بـ Dog
}

يمنع هذا الفحص أخطاء وقت التشغيل من خلال ضمان نجاح عملية التحويل (cast). كما يعيد المعامل القيمة true للأنواع الأب في التسلسل الهرمي:

Dog dog = new Dog();
System.out.println(dog instanceof Dog);     // true
System.out.println(dog instanceof Animal);  // true
System.out.println(dog instanceof Object);  // true

منذ إصدار Java 16، يمكنك دمج التحقق والتحويل (cast) في خطوة واحدة باستخدام مطابقة الأنماط (pattern matching):

if (animal instanceof Dog dog) {
    dog.bark();  // 'dog' تم تحويله بالفعل وجاهز للاستخدام
}

هذا البناء البرمجي الأكثر بساطة يلغي الحاجة لسطر تحويل النوع (cast) المنفصل. لاحظ أن instanceof يعيد false عند اختباره مقابل null، لذا لا تحتاج إلى فحص null بشكل منفصل.

challenge icon

التحدي

سهل

لنقم ببناء نظام فحص للمركبات يستخدم عامل التشغيل instanceof لتحديد أنواع المركبات المختلفة والتعامل معها بأمان. ستقوم بإنشاء تسلسل هرمي للمركبات وكتابة كود يتحقق من النوع الفعلي لكل مركبة قبل الوصول إلى ميزاتها المتخصصة.

ستقوم بتنظيم الكود الخاص بك عبر أربعة ملفات:

  • Vehicle.java: قم بإنشاء الفئة الأساسية التي تشترك فيها جميع المركبات. كل مركبة لها حقل model من نوع (String). قم بتضمين منشئ (constructor) لتهيئته، وطريقة جلب getModel()، وطريقة inspect() التي تطبع: "Inspecting vehicle: " + model
  • Car.java: قم بإنشاء فئة ترث من Vehicle. تمتلك السيارات حقلاً إضافياً numDoors من نوع (int). استخدم super لتهيئة الفئة الأب. أضف طريقة checkDoors() التي تطبع: getModel() + " has " + numDoors + " doors"
  • Motorcycle.java: قم بإنشاء فئة أخرى ترث من Vehicle. تمتلك الدراجات النارية حقلاً hasSidecar من نوع (boolean). أضف طريقة checkSidecar() التي تطبع إما getModel() + " has a sidecar" أو getModel() + " has no sidecar" بناءً على قيمة الـ boolean.
  • Main.java: هنا يصبح instanceof ضرورياً! ستتلقى أربعة مدخلات: طراز السيارة، عدد الأبواب، طراز الدراجة النارية، وما إذا كانت تحتوي على عربة جانبية (true/false).

    قم بإنشاء مصفوفة من مراجع Vehicle تحتوي على Car و Motorcycle. ثم قم بالمرور عبر المصفوفة ولكل مركبة:

    • استدعِ طريقة inspect() الأساسية
    • استخدم instanceof للتحقق مما إذا كانت Car - إذا كان الأمر كذلك، قم بعمل downcast بأمان واستدعِ checkDoors()
    • استخدم instanceof للتحقق مما إذا كانت Motorcycle - إذا كان الأمر كذلك، قم بعمل downcast بأمان واستدعِ checkSidecar()

ستتلقى أربعة مدخلات: طراز السيارة (String)، عدد الأبواب (int)، طراز الدراجة النارية (String)، ووجود عربة جانبية (boolean).

يجب أن يظهر مخرجك أربعة أسطر - لكل مركبة، سترى رسالة الفحص الخاصة بها متبوعة بالفحص الخاص بنوعها. يضمن عامل التشغيل instanceof أنك تستدعي طرق Car فقط على كائنات Car الفعلية وطرق Motorcycle فقط على كائنات Motorcycle الفعلية، مما يمنع حدوث أي ClassCastException!

ورقة مرجعية

يتحقق عامل التشغيل instanceof مما إذا كان الكائن مثيلاً لفئة معينة قبل إجراء التحويل (casting):

Animal animal = new Dog();

if (animal instanceof Dog) {
    Dog dog = (Dog) animal;
    dog.bark();  // Safe to call Dog-specific methods
}

يعيد عامل التشغيل القيمة true لفئة الكائن وجميع الفئات الأب في التسلسل الهرمي:

Dog dog = new Dog();
System.out.println(dog instanceof Dog);     // true
System.out.println(dog instanceof Animal);  // true
System.out.println(dog instanceof Object);  // true

منذ إصدار Java 16، يجمع مطابقة الأنماط (pattern matching) بين التحقق والتحويل في خطوة واحدة:

if (animal instanceof Dog dog) {
    dog.bark();  // 'dog' is already cast and ready to use
}

يعيد عامل التشغيل instanceof القيمة false عند اختباره مقابل null، مما يلغي الحاجة إلى عمليات تحقق منفصلة من القيم الفارغة (null checks).

جرّب بنفسك

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // قراءة المدخلات
        String carModel = scanner.nextLine();
        int numDoors = Integer.parseInt(scanner.nextLine());
        String motorcycleModel = scanner.nextLine();
        boolean hasSidecar = Boolean.parseBoolean(scanner.nextLine());
        
        // TODO: إنشاء كائن Car باستخدام carModel و numDoors
        
        // TODO: إنشاء كائن Motorcycle باستخدام motorcycleModel و hasSidecar
        
        // TODO: إنشاء مصفوفة من مراجع Vehicle تحتوي على Car و Motorcycle
        
        // TODO: التكرار عبر المصفوفة ولكل مركبة:
        // 1. استدعاء الدالة inspect()
        // 2. استخدام instanceof للتحقق مما إذا كانت Car، ثم عمل downcast واستدعاء checkDoors()
        // 3. استخدام instanceof للتحقق مما إذا كانت Motorcycle، ثم عمل downcast واستدعاء checkSidecar()
    }
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس Object Oriented Programming