Java Урок 24: КЛАСС, перегрузка методов

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

Скачать исходники для статьи можно ниже

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

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

Следующий простой пример иллюстрирует перегрузку метода:

class OverloadDemo {
   void test() {
      System.out.println("Параметры отсутствуют");
   }
   // Проверка перегрузки на наличие одного целочисленного параметра.
   void test(int а) {
      System.out.println("а: " + a);
   }
   // Проверка перегрузки на наличие двух целочисленных параметров.
   void test(int a, int b) {
      System.out.println("а и b: " + a + " " + b) ;
   }
   // Проверка перегрузки на наличие параметра типа double
   double test(double a) {
      System.out.println("double a: " + a);
   return a * a;
   }
}

class Overload {
   public static void main(String args[]) {
      OverloadDemo ob = new OverloadDemo();
      double result;
      // вызов всех версий метода test()
      ob.test();
      ob.test(10);
      ob.test(10, 20) ;
      result = ob.test(123.25);
      System.out.println("Результат ob.test(123.25): " + result);
   }
}

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

Параметры отсутствуют
а: 10
а и b: 10 20
double а: 123.25
Результат ob.test(123.25): 15190.5625

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

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

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

Например, рассмотрим следующую программу:

// Применение автоматического преобразования типов к перегрузке,
class OverloadDemo {
   void test() {
      System.out.println("Параметры отсутствуют");
   }

   void test(int a, int b) {
      System.out.println("а и b: " + a + " " + b) ;
   }

   void test(double a) {
   System.out.println("Внутреннее преобразование test(double) a: " + a);
   }
}

class Overload {
   public static void main(String args[]) {
      OverloadDemo ob = new OverloadDemo();
      int i = 88;
      ob.test();
      ob.test(10, 20);
      ob.test(i); // этот оператор вызовет test(double)
      ob.test(123.2); // этот оператор вызовет test(double)
   }
}

Программа создает следующий вывод:

Параметры отсутствуют
а и b: 10 20
Внутреннее преобразование test(double) а: 88
Внутреннее преобразование test(double) а: 123.2

Как видите, эта версия класса OverloadDemo не определяет перегрузку метода test(int). Поэтому при вызове метода test() с целочисленным аргументом внутри класса Overload соответствующий метод отсутствует.

Однако Java может автоматически преобразовать тип integer в тип double, и это преобразование может использоваться для разрешения вызова. Поэтому после того, как версия метода test(int) не обнаружена, Java повышает тип переменной i до double, а затем вызывает метод test(double).
Конечно, если бы метод test(int) был определен, то был бы вызван именно он. Java будет использовать автоматическое преобразование типов только при отсутствии полного соответствия.
Перегрузка методов обеспечивает полиморфизм, поскольку это один из способов реализации в Java концепции “один интерфейс, несколько методов”.
Для пояснения приведем следующие рассуждения. В тех языках, которые не
поддерживают перегрузку методов, каждому методу должно быть присвоено уникальное имя. Однако зачастую желательно реализовать, по сути, один и тот же метод для различных типов данных.

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

Например, в языке С функция abs() возвращает абсолютное значение типа integer, функция labs() — значения типа long integer, а функция fabs () —значения с плавающей точкой.
Поскольку язык С не поддерживает перегрузку, каждая функция должна обладать собственным именем, несмотря на то, что все три функции
выполняют по существу одно и то же действие. В результате в концептуальном смысле ситуация становится более сложной, чем она есть на самом деле.
Хотя каждая функция построена на основе одной и той же концепции, программист вынужден помнить три имени. В Java подобная ситуация не возникает, поскольку все методы вычисления абсолютного значения могут использовать одно и то же имя.
И действительно, стандартная библиотека классов Java содержит метод
вычисления абсолютного значения, названный abs(). Перегруженные версии этого метода для обработки всех числовых типов определены в классе Java Math. Java выбирает для вызова нужную версию метода abs() в зависимости от типа аргумента.

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

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

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

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

В частности, следует перегружать только тесно связанные операции.

Введите свой email адрес для того, чтобы подписаться на мой блог:


knopkisoc

Добавить комментарий