Как перегрузить метод java

Перегрузка и переопределение методов в Java: примеры

Метод в Java — это функция, которая определяет, что умеет делать объект этого класса. Одна из главных задач методов — выполнение действий над данными объекта. Они могут менять значение, преобразовывать данные, выводить их в консоль.

Методы можно перегружать и переопределять. Как это делать и в чём разница между этими двумя механизмами — разберёмся в этой статье.

Перегрузка метода

Перегрузка методов в Java — это использование одного имени метода с разными параметрами.

Чтобы разобраться с этим механизмом, начнём с простого — создадим помощника, который будет здороваться с пользователями.

public class Assistant  
public void sayHello(String name) System.out.println("Добрый день, " + name + "!");
>

public static void main(String[] args) Assistant assistant = new Assistant();
assistant.sayHello("Михаил");
>
>

В консоли будет выведена фраза «Добрый день, Михаил!».

Допустим, Михаил пришёл не один, а с другом Виталием. Сейчас метод реализован так, что помощник поприветствует только Михаила, а Виталия проигнорирует. Чтобы исправить это, реализуем в классе два метода. Имя у них будет одинаковое. Но параметры они принимают разные.

public class Assistant  
public void sayHello(String firstGuest) System.out.println("Добрый вечер, " + firstGuest + "!");
>

public void sayHello(String firstGuest, String secondGuest) System.out.println("Добрый день, " + firstGuest + " и " + secondGuest + "!");
>
public static void main(String[] args) Assistant assistant = new Assistant();
assistant.sayHello("Михаил", "Виталий");
>
>

Теперь в консоли отобразится фраза «Добрый день, Михаил и Виталий!».

Мы уже перегрузили sayHello(). Теперь программа стала более гибкой — помощник может приветствовать сразу двух гостей. Но что произойдёт, если придут трое, четверо или пятеро? Проверим:

public class Assistant  
public void sayHello(String firstGuest) System.out.println("Добрый вечер, " + firstGuest + "!");
>

public void sayHello(String firstGuest, String secondGuest) System.out.println("Добрый день, " + firstGuest + " и " + secondGuest + "!");
>
public static void main(String[] args) Assistant assistant = new Assistant();
assistant.sayHello("Михаил", "Виталий", "Марина");
>
>

В ответ получим ошибку, потому что sayHello() готов принимать только два аргумента. Решение в лоб — перегружать его дальше. Сделать так, чтобы .sayHello() принимал троих, четверых, пятерых и больше гостей. Но это не похоже на гибкую работу программы. Придётся постоянно дописывать код.

Более гибкое решение — передать в качестве параметра аргумент переменной длины (String… names). Это позволит sayHello() принимать любое количество строк. А чтобы выводить в консоль приветствие каждого гостя, используем цикл.

public class Assistant  
public void sayHello(String firstGuest) System.out.println("Добрый вечер, " + firstGuest + "!");
>

public void sayHello(String… names)
for (String name: names) System.out.println("Добрый вечер, " + name + "!");
>
>

public static void main(String[] args) Assistant assistant = new Assistant();
assistant.sayHello("Михаил", "Виталий", "Марина", "Андрей", "Анна");
>

В консоли отобразится приветствие каждого переданного гостя:

Добрый вечер, Михаил!
Добрый вечер, Виталий!
Добрый вечер, Марина!
Добрый вечер, Андрей!
Добрый вечер, Анна!

Порядок аргументов

В примере выше мы не думали о порядке аргументов, потому что все они были строками. Нет разницы, с кем здороваться сначала — с Михаилом или с Анной.

Но порядок аргументов имеет значение, если метод принимает, например, строку и число. Посмотрите:

public class User  
public static void sayYourAge(String greeting, int age) System.out.println(greeting + " " + age);
>

public static void main(String[] args) sayYourAge(20, "Мой возраст - "); //ошибка!
>
>

На этапе компиляции возникнет ошибка, потому что при определении sayYourAge() мы задали, что сначала должна быть строка, а затем — число, но аргументы передали в обратном порядке.

Чтобы исправить ошибку, достаточно передать аргументы в правильном порядке:

public class User  
public static void sayYourAge(String greeting, int age) System.out.println(greeting + " " + age);
>

public static void main(String[] args) sayYourAge("Мой возраст - ", 20);
>
>

Чтобы избежать ошибок, можно сделать перегрузку порядком параметров. Например, вот так:

public class User  
public static void sayYourAge(String greeting, int age) System.out.println(greeting + " " + age);
>
public static void sayYourAge(int age, String greeting) System.out.println(greeting + " " + age);
>

public static void main(String[] args) sayYourAge("Мой возраст - ", 20);
sayYourAge(20, "Мой возраст - ");
>
>

Теперь не имеет значения, в каком порядке передавать аргументы — оба варианты будут понятны программе.

Варианты перегрузки

Из примеров выше можно выделить три варианта перегрузки.

public class Calculator void calculate(int number1, int number2) < > 
void calculate(int number1, int number2, int number3) < >
>
public class Calculator void calculate(int number1, int number2) < > 
void calculate(double number1, double number2) < >
>
public class Calculator void calculate(double number1, int number2) < > 
void calculate(int number1, double number2) < >
>

Напоследок повторим, что означает перегрузка метода в Java . Это механизм языка, который позволяет создавать несколько методов с одинаковым названием, но разными параметрами. Так можно делать не во всех языках.

Перегрузка — это часть полиморфизма, одной из ключевых составляющих объектно-ориентированного программирования. Главный плюс перегрузки в Java — можно использовать схожие методы с одинаковыми именами.

Переопределение метода

Переопределение метода в Java позволяет взять метод родительского класса и создать специфическую реализацию в классе-наследнике.

Проще понять на примере. Допустим, вы создаёте класс Animal с методом voice(). Он нужен для того, чтобы животное могло подать голос:

public class Animal  
public void voice()
System.out.println("Говори!");
>
>

И сразу возникает проблема — все животные издают разные звуки. Можно создать для каждого отдельный метод. Например, у кошки это будет voiceCat(), а у собаки — voiceDog(). Но представьте, сколько строк кода придётся написать, чтобы дать возможность всем животным подать голос?

Здесь на помощь и приходит механизм переопределения в Java. Он позволяет заменить реализацию в классе-наследнике. Посмотрим на примере кошки и собаки:

public class Cat extends Animal  
@Override
public void voice() System.out.println("Мяу!");
>
>

public class Dog extends Animal
@Override
public void voice() System.out.println("Гав!");
>
>

В выводе отобразится сначала «Мяу», а затем — «Гав». Чтобы добиться такого результата, нужно:

  1. В классе-наследнике создать метод с таким же именем, как в родительском классе.
  2. Добавить перед ним аннотацию @Override (с английского переводится как «переопределён»). Эта аннотация сообщит компилятору, что это не ошибка, вы намеренно переопределяете метод. Отметим, что наличие аннотации необязательно. Если в дочернем классе создать метод с такой же сигнатурой, как у родительского, метод все равно переопределится. Но рекомендуется ставить аннотацию всегда, так как это улучшает «читабельность» кода, а также при этом компилятор проверит на этапе сборки, что такой метод действительно есть в родительском классе.

Собственная реализация пишется для каждого класса-наследника. Если этого не сделать, то будет использована реализация родительского класса.

Даже после переопределения вы можете обратиться к методу родительского класса при условии, что он не определён модификатором private. Для этого используется ключевое слово super:

Ограничения при переопределении

У переопределения методов класса в Java есть ряд ограничений.

  • Название метода должно быть таким же, как у метода родителя (то есть сигнатура метода должна быть одинаковой).
  • Аргументы должны оставаться такими же, как у метода родителя.
  • Тип возвращаемого значения должен быть таким же, как у метода родителя.
  • Модификатор доступа должен быть таким же, как у метода родителя.
  • Окончательные методы (final) нельзя переопределять. Это один из способов запрета переопределения — объявить метод с помощью ключевого слова final.
class Parent final void show() <>
>

class Child extends Parent void show() <>
>

Такой код вернёт ошибку, потому что в родительском классе использовано ключевое слово final.

  • Статические методы (static) нельзя переопределять. Если вы определите в классе-наследнике такую же сигнатуру метода, как в родительском классе, то выполните сокрытие. Подробнее об этом вы можете прочитать в документации .
  • Приватные методы (private) нельзя переопределять, так как они связываются на этапе компиляции, а не выполнения.
  • Нельзя сужать модификатор доступа — например, с public до private. Расширение уровня доступа возможно.
  • Нельзя менять тип возвращаемого значения, однако можно сузить возвращаемое значение, если они совместимы.

Переопределение класса в Java подчиняется указанным выше правилам, которые необходимо соблюдать.

Собственные правила переопределения есть у отдельных методов. Например, equals() и hashCode(). Самое важное условие — если вы переопределяете equals(), то должны переопределить и hashCode(). В противном случае классы и методы, которые пользуются контрактами стандартной реализации этих двух методов, могут работать с ошибками. Подробнее от этом мы рассказали в отдельной статье.

Заключение

Переопределение и перегрузка методов в Java — важные части полиморфизма, однако это разные механизмы. При перегрузке вы создаёте внутри одного класса много методов с одинаковым названием, но разными параметрами. При переопределении вы берёте один и тот же метод и заставляете его делать разные вещи в зависимости от того, в каком классе его вызвали.

Но есть характеристики, в которых перегрузка и переопределение Java похожи. Оба механизма помогают сделать код чище и читабельнее, а также уменьшить количество ошибок при выполнении программ.

Источник

Как перегрузить метод java

В программе мы можем использовать методы с одним и тем же именем, но с разными типами и/или количеством параметров. Такой механизм называется перегрузкой методов (method overloading).

public class Program < public static void main(String[] args) < System.out.println(sum(2, 3)); // 5 System.out.println(sum(4.5, 3.2)); // 7.7 System.out.println(sum(4, 3, 7)); // 14 >static int sum(int x, int y) < return x + y; >static double sum(double x, double y) < return x + y; >static int sum(int x, int y, int z) < return x + y + z; >>

Здесь определено три варианта или три перегрузки метода sum() , но при его вызове в зависимости от типа и количества передаваемых параметров система выберет именно ту версию, которая наиболее подходит.

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

public class Program < public static void main(String[] args) < System.out.println(sum(2, 3)); System.out.println(sum(4, 3)); >static int sum(int x, int y) < return x + y; >static double sum(int x, int y) < return x + y; >>

Однако перегрузкой это не будет считаться. Более того такая программа некорректна и попросту не скомилируется, так как метод с одним и тем же количеством и типом параметров определен несколько раз.

Источник

Читайте также:  Test
Оцените статью