Перегрузка методов класса в Java

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

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

Для того чтобы перегрузить метод, достаточно объявить его новый вариант, отлича­ющийся от уже существующих, а все остальное сделает компилятор. Нужно лишь со­блюсти одно условие: тип и/или число параметров в каждом из перегружаемых методов должны быть разными.

Одного лишь различия в типах возвращаемых значений для этой цели недостаточно. (Информации о возвращаемом типе не всегда будет хватать Java для принятия решения о том, какой именно метод должен использоваться.)

Конечно, пе­регружаемые методы могут иметь разные возвращаемые типы, но при вызове метода выполняется лишь тот его вариант, в котором параметры соответствуют передаваемым аргументам.

Ниже приведен простой пример программы, демонстрирующий перегрузку методов.

Выполнение этой программы дает следующий результат:

Как видите, метод ovlDemo() перегружается четырежды. В первой его версии па­раметры не предусмотрены, во второй — определен один целочисленный параметр, в третьей — два целочисленных параметра, в четвертой — два параметра типа double.

Обратите внимание на то, что первые два варианта метода ovlDemo() имеют тип void, а два другие возвращают значение. Тип возвращаемого значения не учитывается при перегрузке методов. Следовательно, попытка определить два варианта метода ovlDemo() так, как показано ниже, приводит к ошибке.

Как поясняется в комментариях к приведенному выше фрагменту кода, отличия воз­вращаемых типов недостаточно для перегрузки методов.

Как мы знаем, в Java применяется автоматическое приведение типов. Это приведение распространяется и на типы параметров перегружаемых методов. В качестве примера рассмотрим следующий фрагмент кода.

Выполнение этого фрагмента кода дает следующий результат:

В данном примере определены только два варианта метода f(): один принимает параметр типа int, а второй — параметр типа double.

Но передать методу f() можно также значение типа byte, short и float. Значения типа byte и short исполняющая система Java автоматически преобразует в тип int. В результате будет вызван вариант метода f(int). А если параметр имеет значение типа float, то оно преобразуется в тип doube, и далее вызывается вариант метода f(double).

Важно понимать, что автоматическое преобразование типов выполняется лишь в от­сутствие прямого соответствия типов параметра и аргумента. В качестве примера ниже представлена другая версия предыдущей программы, в которой добавлен вариант метода f() с параметром типа byte.

Выполнение этой версии программы дает следующий результат.

Поскольку в данной программе предусмотрена версия метода f(), которая принима­ет параметр типа byte, то при вызове этого метода с аргументом типа byte выполняется вызов f (byte), и автоматического преобразования типа byte в тип int не происходит.

Перегрузка методов поддерживает полиморфизм, поскольку она является одним из способов реализации парадигмы «один интерфейс — множество методов». Для того чтобы стало понятнее, как и для чего это делается, необходимо принять во внимание следующее соображение: в языках программирования, не поддерживающих перегрузку методов, каждый метод должен иметь уникальное имя.

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

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

Например,в языке С функция abs() возвращает абсолютное значение числа типа int, функция labs() — абсолютное значение числа типа long, а функция fabs() — абсолютное зна­чение числа с плавающей точкой.

Объясняется это тем, что в С не поддерживается пе­регрузка, и поэтому каждая из функций должна обладать своим собственным именем,несмотря на то что все они выполняют одинаковые действия. Это приводит к нео­правданному усложнению процесса написания программ.

Разработчику приходится не только представлять себе действия, выполняемые функциями, но и помнить все три их имени. Такая ситуация не возникает в Java, потому что все методы, вычисляющие абсо­лютное значение, имеют одно и то же имя.

В стандартной библиотеке Java для вычисле­ния абсолютного значения предусмотрен метод abs(). Его перегрузка осуществляется в классе Math для обработки значений всех числовых типов.

Решение о том, какой имен­но вариант метода abs() должен быть вызван, исполняющая система Java принимает, исходя из типа аргумента.

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

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

Когда метод перегружается, каждая его версия может выполнять какое угодно дей­ствие. Для установления взаимосвязи перегружаемых методов не существует какого-то твердого правила, но с точки зрения правильного стиля программирования перегрузка методов подразумевает подобную взаимосвязь. Следовательно, использовать одно и тоже имя для несвязанных друг с другом методов не следует, хотя это и возможно.

Напри­мер, имя sqr можно было бы выбрать для методов, возвращающих квадрат и квадрат­ный корень числа с плавающей точкой. Но ведь это принципиально разные операции.

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

Стоит отметить, что, программисты на Java часто употребляют термин сигнатура. Что это такое?

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

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

Интересное видео для читателей: