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

إعادة تعريف الدوال (@Override)

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

يسمح تجاوز الطريقة (Method overriding) للفئة الفرعية (subclass) بتقديم تنفيذها الخاص لدالة (method) معرفة مسبقاً في فئتها الأب (parent class). هذه هي الطريقة التي تخصص بها الفئات الأبناء السلوك الموروث لتناسب احتياجاتها الخاصة.

عندما تقوم بإعادة تعريف (override) دالة (method)، فإن نسخة الفئة الفرعية (subclass) تحل محل نسخة الفئة الأب (parent) تماماً بالنسبة لكائنات تلك الفئة الفرعية. يجب أن تمتلك الدالة نفس الاسم، ونوع الإرجاع، والمعاملات (parameters) كما في دالة الفئة الأب:

public class Animal {
    public void makeSound() {
        System.out.println("Some generic sound");
    }
}

public class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Woof!");
    }
}

public class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Meow!");
    }
}

تخبر الملاحظة التوضيحية @Override المترجم (compiler) أنك تنوي تجاوز (override) طريقة في الفئة الأب. ورغم أنها اختيارية، إلا أنه يوصى بها بشدة لأن المترجم سيكتشف الأخطاء إذا أخطأت في كتابة اسم الطريقة أو استخدمت معاملات خاطئة:

@Override
public void makeSound() { }  // صحيح - المترجم يتحقق من هذا

public void makesound() { }  // خطأ مطبعي! ينشئ طريقة جديدة بدلاً من التجاوز

عندما تستدعي طريقة تم تجاوزها (overridden method)، يقوم Java بتنفيذ الإصدار الذي ينتمي إلى نوع الكائن الفعلي:

Dog dog = new Dog();
dog.makeSound();  // النتيجة: Woof!

Cat cat = new Cat();
cat.makeSound();  // النتيجة: Meow!

تذكر من الدرس السابق أنه يمكنك استخدام super.methodName() داخل طريقة تم تجاوزها (overridden method) إذا كنت لا تزال ترغب في تضمين سلوك الفئة الأب مع الكود الجديد الخاص بك.

challenge icon

التحدي

سهل

لنقم ببناء نظام إشعارات يوضح كيف يمكن للفئات الفرعية (subclasses) تجاوز (override) أساليب الفئة الأب لتقديم سلوكها المتخصص. سترى كيف يساعد التعليق التوضيحي @Override في اكتشاف الأخطاء وكيف يمكن لكل فئة فرعية تخصيص الأساليب الموروثة.

ستقوم بإنشاء ثلاثة ملفات لتنظيم الكود الخاص بك:

  • Notification.java: أنشئ الفئة الأب التي تمثل إشعاراً عاماً. يجب أن تحتوي على:
    • حقل خاص (private field) لـ message (String)
    • منشئ (constructor) يقبل الرسالة
    • أسلوب getMessage() يعيد الرسالة
    • أسلوب send() يطبع: Sending notification: [message]
  • EmailNotification.java: أنشئ فئة فرعية ترث من Notification وتخصص كيفية إرسال الإشعارات عبر البريد الإلكتروني:
    • حقل خاص لعنوان البريد الإلكتروني recipient (String)
    • منشئ يأخذ كلاً من الرسالة والمستلم، باستخدام super(message) للجزء الخاص بالفئة الأب
    • تجاوز أسلوب send() باستخدام التعليق التوضيحي @Override لطباعة: Emailing [recipient]: [message]
  • Main.java: وضح كيف ينتج نفس اسم الأسلوب سلوكاً مختلفاً اعتماداً على نوع الكائن. ستتلقى مدخلين: رسالة وعنوان بريد إلكتروني. أنشئ كلاً من Notification عادي و EmailNotification بنفس الرسالة، ثم استدعِ send() على كل منهما لرؤية المخرجات المختلفة.

ستتلقى مدخلين: الرسالة (String) وعنوان البريد الإلكتروني للمستلم (String).

يجب أن يظهر مخرجك سطرين - الأول من أسلوب send() الخاص بالفئة الأب، ثم من النسخة التي تم تجاوزها في EmailNotification. يوضح هذا كيف يسمح تجاوز الأساليب (method overriding) للفئات الفرعية باستبدال السلوك الموروث بتنفيذها الخاص.

ورقة مرجعية

يسمح تجاوز الدوال (Method overriding) للفئة الفرعية (subclass) بتقديم تنفيذ خاص بها لدالة معرفة مسبقاً في الفئة الأب (parent class). يجب أن تمتلك الدالة التي تم تجاوزها نفس الاسم، ونوع الإرجاع، والمعاملات الخاصة بالدالة في الفئة الأب.

public class Animal {
    public void makeSound() {
        System.out.println("Some generic sound");
    }
}

public class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Woof!");
    }
}

يُعد التعليق التوضيحي @Override اختيارياً ولكنه موصى به بشدة. فهو يخبر المترجم (compiler) أنك تنوي تجاوز دالة في الفئة الأب، مما يساعد في اكتشاف الأخطاء مثل كتابة أسماء الدوال بشكل خاطئ أو استخدام معاملات غير صحيحة:

@Override
public void makeSound() { }  // صحيح - يتحقق المترجم من هذا

public void makesound() { }  // خطأ مطبعي! ينشئ دالة جديدة بدلاً من التجاوز

عند استدعاء دالة تم تجاوزها، تقوم Java بتنفيذ الإصدار الذي ينتمي إلى نوع الكائن الفعلي:

Dog dog = new Dog();
dog.makeSound();  // Output: Woof!

Cat cat = new Cat();
cat.makeSound();  // Output: Meow!

يمكنك استخدام super.methodName() داخل الدالة التي تم تجاوزها لتضمين سلوك الفئة الأب جنباً إلى جنب مع الكود الجديد الخاص بك.

جرّب بنفسك

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // قراءة المدخلات
        String message = scanner.nextLine();
        String recipient = scanner.nextLine();
        
        // TODO: إنشاء كائن Notification مع الرسالة
        
        // TODO: إنشاء كائن EmailNotification مع الرسالة والمستلم
        
        // TODO: استدعاء send() على كائن Notification
        
        // TODO: استدعاء send() على كائن EmailNotification
    }
}
quiz iconاختبر نفسك

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

جميع دروس Object Oriented Programming