Метод в Java — это функция, которая определяет, что умеет делать объект этого класса. Одна из главных задач методов — выполнение действий над данными объекта. Они могут менять значение, преобразовывать данные, выводить их в консоль.
Методы можно перегружать и переопределять. Как это делать и в чём разница между этими двумя механизмами — разберёмся в этой статье.
Перегрузка метода
Перегрузка методов в Java — это использование одного имени метода с разными параметрами.
Чтобы разобраться с этим механизмом, начнём с простого — создадим помощника, который будет здороваться с пользователями.
В консоли будет выведена фраза «Добрый день, Михаил!».
Допустим, Михаил пришёл не один, а с другом Виталием. Сейчас метод реализован так, что помощник поприветствует только Михаила, а Виталия проигнорирует. Чтобы исправить это, реализуем в классе два метода. Имя у них будет одинаковое. Но параметры они принимают разные.
Теперь в консоли отобразится фраза «Добрый день, Михаил и Виталий!».
Мы уже перегрузили sayHello(). Теперь программа стала более гибкой — помощник может приветствовать сразу двух гостей. Но что произойдёт, если придут трое, четверо или пятеро? Проверим:
В ответ получим ошибку, потому что sayHello() готов принимать только два аргумента. Решение в лоб — перегружать его дальше. Сделать так, чтобы .sayHello() принимал троих, четверых, пятерых и больше гостей. Но это не похоже на гибкую работу программы. Придётся постоянно дописывать код.
Более гибкое решение — передать в качестве параметра аргумент переменной длины (String… names). Это позволит sayHello() принимать любое количество строк. А чтобы выводить в консоль приветствие каждого гостя, используем цикл.
В консоли отобразится приветствие каждого переданного гостя:
Порядок аргументов
В примере выше мы не думали о порядке аргументов, потому что все они были строками. Нет разницы, с кем здороваться сначала — с Михаилом или с Анной.
Но порядок аргументов имеет значение, если метод принимает, например, строку и число. Посмотрите:
На этапе компиляции возникнет ошибка, потому что при определении sayYourAge() мы задали, что сначала должна быть строка, а затем — число, но аргументы передали в обратном порядке.
Чтобы исправить ошибку, достаточно передать аргументы в правильном порядке:
Чтобы избежать ошибок, можно сделать перегрузку порядком параметров. Например, вот так:
Теперь не имеет значения, в каком порядке передавать аргументы — оба варианты будут понятны программе.
Облачные серверы
по всему миру с почасовой оплатой.
Варианты перегрузки
Из примеров выше можно выделить три варианта перегрузки.
- По количеству параметров.
- По типам параметров:
- По порядку параметров:
Напоследок повторим, что означает перегрузка метода в Java. Это механизм языка, который позволяет создавать несколько методов с одинаковым названием, но разными параметрами. Так можно делать не во всех языках.
Перегрузка — это часть полиморфизма, одной из ключевых составляющих объектно-ориентированного программирования. Главный плюс перегрузки в Java — можно использовать схожие методы с одинаковыми именами.
Переопределение метода
Переопределение метода в Java позволяет взять метод родительского класса и создать специфическую реализацию в классе-наследнике.
Проще понять на примере. Допустим, вы создаёте класс Animal с методом voice(). Он нужен для того, чтобы животное могло подать голос:
И сразу возникает проблема — все животные издают разные звуки. Можно создать для каждого отдельный метод. Например, у кошки это будет voiceCat(), а у собаки — voiceDog(). Но представьте, сколько строк кода придётся написать, чтобы дать возможность всем животным подать голос?
Здесь на помощь и приходит механизм переопределения в Java. Он позволяет заменить реализацию в классе-наследнике. Посмотрим на примере кошки и собаки:
В выводе отобразится сначала «Мяу», а затем — «Гав». Чтобы добиться такого результата, нужно:
- В классе-наследнике создать метод с таким же именем, как в родительском классе.
- Добавить перед ним аннотацию @Override (с английского переводится как «переопределён»). Эта аннотация сообщит компилятору, что это не ошибка, вы намеренно переопределяете метод. Отметим, что наличие аннотации необязательно. Если в дочернем классе создать метод с такой же сигнатурой, как у родительского, метод все равно переопределится. Но рекомендуется ставить аннотацию всегда, так как это улучшает «читабельность» кода, а также при этом компилятор проверит на этапе сборки, что такой метод действительно есть в родительском классе.
Собственная реализация пишется для каждого класса-наследника. Если этого не сделать, то будет использована реализация родительского класса.
Даже после переопределения вы можете обратиться к методу родительского класса при условии, что он не определён модификатором private. Для этого используется ключевое слово super:
Ограничения при переопределении
У переопределения методов класса в Java есть ряд ограничений.
- Название метода должно быть таким же, как у метода родителя (то есть сигнатура метода должна быть одинаковой).
- Аргументы должны оставаться такими же, как у метода родителя.
- Тип возвращаемого значения должен быть таким же, как у метода родителя.
- Модификатор доступа должен быть таким же, как у метода родителя.
- Окончательные методы (final) нельзя переопределять. Это один из способов запрета переопределения — объявить метод с помощью ключевого слова final.
Например:
Такой код вернёт ошибку, потому что в родительском классе использовано ключевое слово final.
- Статические методы (static) нельзя переопределять. Если вы определите в классе-наследнике такую же сигнатуру метода, как в родительском классе, то выполните сокрытие. Подробнее об этом вы можете прочитать в документации.
- Приватные методы (private) нельзя переопределять, так как они связываются на этапе компиляции, а не выполнения.
- Нельзя сужать модификатор доступа — например, с public до private. Расширение уровня доступа возможно.
- Нельзя менять тип возвращаемого значения, однако можно сузить возвращаемое значение, если они совместимы.
Переопределение класса в Java подчиняется указанным выше правилам, которые необходимо соблюдать.
Собственные правила переопределения есть у отдельных методов. Например, equals() и hashCode(). Самое важное условие — если вы переопределяете equals(), то должны переопределить и hashCode(). В противном случае классы и методы, которые пользуются контрактами стандартной реализации этих двух методов, могут работать с ошибками. Подробнее от этом мы рассказали в отдельной статье.
Выгодные тарифы на облако в Timeweb Cloud
477 ₽/мес
657 ₽/мес
Заключение
Переопределение и перегрузка методов в Java — важные части полиморфизма, однако это разные механизмы. При перегрузке вы создаёте внутри одного класса много методов с одинаковым названием, но разными параметрами. При переопределении вы берёте один и тот же метод и заставляете его делать разные вещи в зависимости от того, в каком классе его вызвали.
Но есть характеристики, в которых перегрузка и переопределение Java похожи. Оба механизма помогают сделать код чище и читабельнее, а также уменьшить количество ошибок при выполнении программ.
