Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Модуль 3. Урок 5. Аннотация @Override в Java. Введение в Java

Переопределение методов. Аннотация @Override

Переопределение метода (англ. Method overriding) — это возможность реализовать метод так, что бы он имел идентичную сигнатуру с методом класса-предка, но предоставлял иное поведение, не вызывая коллизий при его использовании. Так же это один из инструментов реализации полиморфизма.

То есть, у нас может быть во всех классах потомках метод, у которого совпадают с методом класса-предка такие параметры: имя, перечень аргументов, возвращаемый тип, модификатор доступа. Отличия будут только в внутренней реализации этих методов. А использование таких одноименных методов не приведет к коллизии как, например, в случае с одноименными полями в методах и классах.

Переопределяя метод — обязательно помечайте его аннотацией @Override! Это не только спасет от потенциальных ошибок, но и повысит читаемость кода. Переопределять можно только нестатические методы.

Рассмотрим это на примере классов пакета view части проекта "XO".

Вот тут можно скачать репу с кодом из примеров.

Для начала, создадим вот такие классы:

package xo.view;
public class View {
    String name = "It is a view.";

    public void show() {
        System.out.println("Метод класса View.");
    }
}
package xo.view;
public class SecondView extends View {
    String name = "It is a secondView.";

    @Override
    public void show() {
        System.out.println("Сообщение из класса SecondView.");
    }
}
package xo.view;
public final class ThirdView extends SecondView {
    String name = "It is a thirdView.";

    @Override
    public void show() {
        System.out.println("Сообщение из класса ThirdView.");
    }
}

Благодаря @Override мы явно указываем, что метод show не просто какой-то локальный метод, а что это такой же метод, как и в классе-предке, но с новым поведением. В данном случае — сообщением.

И что это нам дает?

Переопределение методов дает возможность вызывать методы классов-наследников через ссылки классов предков. Что кажется противоречит принципу доступности членов классов в наследовании в java (потомкам доступны свойства предков, а не наоборот).

Напомним, невозможность вызывать члены потомка из предка, на примере следующего кода:

package xo;
import xo.view.SecondView;
import xo.view.ThirdView;
import xo.view.View;
public class Main {
    public static void main(String[] args) {
        View view = new View();
        printName(view);

        SecondView secondView = new SecondView();
        printName(secondView);

        ThirdView thirdView = new ThirdView();
        printName(thirdView);
    }
    private static void printName(View someView) {
        System.out.println(someView.name);
    }
}

Результатом работы трех вызовов метода printName будет одна и та же надпись: It is a view.. Копируйте код, пробуйте! Потому что ссылка someView ограничена типом View и не может получить доступ к полям потомков класса View. Несмотря на идентичность имен этих полей.

А как вызвать метод потомка из ссылки типа предка?

Просто вызвать, если он там переопределен. Перепишем пример вызовов так:

package xo;
import xo.view.SecondView;
import xo.view.ThirdView;
import xo.view.View;
public class Main {
    public static void main(String[] args) {
        View view = new View();
        callMethod(view);

        SecondView secondView = new SecondView();
        callMethod(secondView);

        ThirdView thirdView = new ThirdView();
        callMethod(thirdView);
    }
    private static void callMethod(View someView) {
        someView.show();
    }
}

Теперь на экран будет выведено три различных сообщения: Метод класса View., Сообщение из класса SecondView., Сообщение из класса ThirdView..

Как это работает?

Даже в байткоде скомпилированной программы будет происходить вызов метода show у типа View. Но в момент исполнения этого байткода JVM получит ссылку на конкретный объект и полезет смотреть его перечень методов (vtable). В этой таблице находятся ссылки на все методы текущего объекта. И, в нашем случае, метод show там будет, даже если бы мы его не переопределили ни в одном из потомков. Если бы мы show не переопределили ни в одном из потомков, то в vtable их объектов (инстансов) была бы ссылка на один и тот же метод show класса View. Но, поскольку мы таки переопределили метод show, то в vtable каждого объекта класса-потомка будет ссылка не на родительский метод show, а на свой локальный переопределенный метод show.

Вот так java понимает какой именно метод стоит вызывать в работе с переопределением методов.


В предыдущем уроке было сказано, что все классы в мире java прямо или опосредовано наследуются от класса Object. И Вы самостоятельно можете провести эксперименты в коде, по этой теме. В файлах, из выше упомянутого репозитория, Вы можете найти класс Board с переопределенным методом класса ObjecttoString(). Попробуйте реализовать свои toString() для остальных классов, протестируйте их. Так же попробуйте добавить в View-классы методы gеtName() и вызвать их из класса Main.

Дополнительная практика по теме.

Полезные ссылки


Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты.

Ошибки, сложный материал, вопросы >
Нашли опечатку или неточность?

Выделите текст, нажмите ctrl + enter и отправьте его нам. В течение нескольких дней мы исправим ошибку или улучшим формулировку.

Что-то не получается или материал кажется сложным?

Загляните в раздел «Обсуждение»:

  • задайте вопрос. Вы быстрее справитесь с трудностями и прокачаете навык постановки правильных вопросов, что пригодится и в учёбе, и в работе программистом;
  • расскажите о своих впечатлениях. Если курс слишком сложный, подробный отзыв поможет нам сделать его лучше;
  • изучите вопросы других учеников и ответы на них. Это база знаний, которой можно и нужно пользоваться.
Об обучении на Хекслете

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
900
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно.

  • 120 курсов, 2000+ часов теории
  • 900 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы соглашаетесь c «Политикой конфиденциальности» и «Условиями оказания услуг»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff

Есть вопрос или хотите участвовать в обсуждении?

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы соглашаетесь c «Политикой конфиденциальности» и «Условиями оказания услуг»