Menu
Coddy logo textTech

Переопределение методов (@Override)

Часть раздела Объектно-ориентированное программирование путешествия по Java на Coddy — урок 22 из 87.

Переопределение методов позволяет подклассу предоставить собственную реализацию метода, который уже определен в его родительском классе. Так дочерние классы настраивают унаследованное поведение в соответствии со своими конкретными потребностями.

Когда вы переопределяете метод, версия подкласса полностью заменяет версию родительского класса для объектов этого подкласса. Метод должен иметь то же имя, тип возвращаемого значения и параметры, что и родительский метод:

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 сообщает компилятору о вашем намерении переопределить родительский метод. Хотя она необязательна, её настоятельно рекомендуется использовать, так как компилятор обнаружит ошибки, если вы случайно допустите опечатку в имени метода или используете неверные параметры:

@Override
public void makeSound() { }  // Правильно — компилятор проверяет это

public void makesound() { }  // Опечатка! Создает новый метод вместо переопределения

Когда вы вызываете переопределенный метод, Java выполняет версию, которая принадлежит фактическому типу объекта:

Dog dog = new Dog();
dog.makeSound();  // Вывод: Woof!

Cat cat = new Cat();
cat.makeSound();  // Вывод: Meow!

Помните из предыдущего урока, что вы можете использовать super.methodName() внутри переопределенного метода, если вы все еще хотите включить поведение родителя вместе с вашим новым кодом.

challenge icon

Задание

Легко

Давайте создадим систему уведомлений, которая демонстрирует, как подклассы могут переопределять родительские методы для обеспечения собственного специализированного поведения. Вы увидите, как аннотация @Override помогает отлавливать ошибки и как каждый подкласс может настраивать унаследованные методы.

Вы создадите три файла для организации вашего кода:

  • Notification.java: Создайте родительский класс, представляющий общее уведомление. Он должен иметь:
    • Приватное поле для message (String)
    • Конструктор, принимающий сообщение
    • Метод 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. Это демонстрирует, как переопределение методов позволяет подклассам заменять унаследованное поведение своей собственной реализацией.

Шпаргалка

Переопределение методов позволяет подклассу предоставить собственную реализацию метода, уже определенного в его родительском классе. Переопределенный метод должен иметь то же имя, тип возвращаемого значения и параметры, что и родительский метод.

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 является необязательной, но настоятельно рекомендуется. Она сообщает компилятору о вашем намерении переопределить родительский метод, помогая обнаруживать ошибки, такие как опечатки в именах методов или неверные параметры:

@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 с сообщением message
        
        // TODO: Создайте объект EmailNotification с сообщением message и получателем recipient
        
        // TODO: Вызовите метод send() у объекта Notification
        
        // TODO: Вызовите метод send() у объекта EmailNotification
    }
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование