Перегрузка методов
Напомним, что имя функции в сочетании с числом параметров и их типами называется сигнатурой функции. Тип возвращаемого значения и имена параметров в сигнатуру не входят. Понятие сигнатуры важно при задании подпрограмм с одинаковыми именами, но разными списками параметров – перегрузке (overloading) подпрограмм. Методы, имеющие одинаковое имя, но разные сигнатуры, разрешается перегружать. Если же сигнатуры совпадают, перегрузка запрещена. Для задания перегруженных методов в Java не требуется никаких дополнительных действий по сравнению с заданием обычных методов. Если же перегрузка запрещена, компилятор выдаст сообщение об ошибке.
Чаще всего перегружают конструкторы при желании иметь разные их варианты, так как имя конструктора определяется именем класса. Например, рассмотренные ранее конструкторы
Circle(Graphics g, Color bgColor){
…
}
и
Circle(Graphics g, Color bgColor, int r){
…
}
отличаются числом параметров, поэтому перегрузка разрешена.
Вызов перегруженных методов синтаксически не отличается от вызова обычных методов, но всё-таки в ряде случаев возникает некоторая специфика из-за неочевидности того, какой вариант метода будет вызван. При разном числе параметров такой проблемы, очевидно, нет. Если же два варианта методов имеют одинаковое число параметров, и отличие только в типе одного или более параметров, возможны логические ошибки.
Напишем класс Math1, в котором имеется подпрограмма-функция product , вычисляющая произведение двух чисел, у которой имеются варианты с разными целыми типами параметров. Пример полезен как для иллюстрации проблем, связанных с вызовом перегруженных методов, так и для исследования проблем арифметического переполнения.
public class Math1 {
public static byte product(byte x, byte y){
return x*y;
}
public static short product(short x, short y){
return x*y;
}
public static int product(int x, int y){
return x*y;
}
public static char product(char x, char y){
return x*y;
}
public static long product(long x, long y){
return x*y;
}
}
Такое задание методов разрешено, так как сигнатуры перегружаемых вариантов различны. Обратим внимание на типы возвращаемых значений – они могут задаваться по желанию программиста. Подпрограммы заданы как методы класса (static) для того, чтобы при их использовании не пришлось создавать объект.
Если бы мы попытались задать такие варианты методов:
public static byte product(byte x, byte y){
return x*y;
}
public static int product(byte a, byte b){
return a*b;
}
то компилятор выдал бы сообщение об ошибке, так как у данных вариантов одинаковая сигнатура. - Ни тип возвращаемого значения, ни имена параметров на сигнатуру не влияют.
Если при вызове метода product параметры имеют типы, совпадающие с заданными в одном из перегруженных вариантов, всё просто. Но что произойдёт в случае, когда в качестве параметра будут переданы значения типов byte и int? Какой вариант будет вызван? Проверка идёт при компиляции программы, при этом перебираются все допустимые варианты. В нашем случае это product(int x, int y) и product(long x, long y). Остальные варианты не подходят из-за типа второго параметра – тип подставляемого значенния должен иметь диапазон значений, “вписывающийся” в диапазон вызываемого метода. Из допустимых вариантов выбирается тот, который ближе по типу параметров, то есть в нашем случае product(int x, int y).
Если среди перегруженных методов среди разрешённых вариантов не удаётся найти предпочтительный, при компиляции класса, где делается вызов, выдаётся диагностика ошибки. Так бы случилось, если бы мы имели следующую реализацию класса Math2
public class Math2 {
public static int product(int x, byte y){
return x*y;
}
public static int product(byte x, int y){
return x*y;
}
}
и в каком-нибудь другом классе имели переменные byte b1, b2 и сделали вызов Math1.product(b1,b2). Оба варианта перегруженного метода подходят, и выбрать более подходящий невозможно. Отметим, что класс Math2 при этом компилируется без проблем – в самом нём ошибок нет. Проблема в том классе, который его использует.
Самая неприятная особенность перегрузки – вызов не того варианта метода, на который рассчитывал программист. Особо опасные ситуации при этом возникают в случае, когда перегруженные методы отличаются типом параметров, и в качестве таких параметров выступают объектные переменные. В этом случае близость совместимых типов определяется по близости в иерархии наследования – по числу этапов наследования. Отметим, что выбор перегруженного варианта проводится статически, на этапе компиляции. Поэтому тип, используемый для этого выбора, определяется типом объектной переменной, передаваемой в качестве параметра, а не типом объекта, который этой переменной назначен.
- Содержание
- Глава 1. Общие представления о языке Java 6
- Глава 2. Объектно-ориентированное проектирование и платформа NetBeans 26
- Глава 3. Примитивные типы данных и операторы для работы с ними 78
- Глава 4. Работа с числами в языке Java 95
- Глава 5. Управляющие конструкции 112
- Глава 6. Начальные сведения об объектном программировании 128
- Глава 7. Важнейшие объектные типы 175
- Введение
- Глава 1. Общие представления о языке Java
- 1.1. Java и другие языки программирования. Системное и прикладное программирование
- 1.2. Виртуальная Java-машина, байт-код, jit-компиляция. Категории программ, написанных на языке Java
- 1.3.Алфавит языка Java. Десятичные и шестнадцатеричные цифры и целые числа. Зарезервированные слова Алфавит языка Java
- Десятичные и шестнадцатеричные цифры и целые числа
- Зарезервированные слова языка Java
- 1.4. Управляющие последовательности. Символы Unicode. Специальные символы Управляющие последовательности
- Простые специальные символы
- Составные специальные символы
- 1.5.Идентификаторы. Переменные и типы. Примитивные и ссылочные типы
- Краткие итоги по главе 1
- Задания
- Глава 2. Объектно-ориентированное проектирование и платформа NetBeans
- 2.1.Процедурное и объектно-ориентированное программирование. Инкапсуляция
- 2.2. Работа со ссылочными переменными. Сборка мусора
- 2.3. Проекты NetBeans. Пакеты. Уровни видимости классов. Импорт классов
- 2.4. Базовые пакеты и классы Java
- 2.5. Создание в NetBeans простейшего приложения Java
- 2.6. Компиляция файлов проекта и запуск приложения
- 2.7. Структура проекта NetBeans
- 2.8. Создание в NetBeans приложения Java с графическим интерфейсом
- 2.9. Редактор экранных форм
- 2.10. Внешний вид приложения
- 2.11. Ведение проектов
- 2.11. Редактирование меню экранной формы
- 2.12. Создание нового класса
- 2.13. Документирование исходного кода в Java
- 2.14. Основные компоненты пакетов swing и awt
- 2.15. Технологии Java и .Net
- Краткие итоги по главе 2
- Задания
- Глава 3. Примитивные типы данных и операторы для работы с ними
- 3.1.Булевский (логический) тип
- 3.2.Целые типы, переменные, константы
- 3.3.Основные операторы для работы с целочисленными величинами
- 3.4.Вещественные типы и класс Math
- 3.5.Правила явного и автоматического преобразования типа при работе с числовыми величинами
- 3.6. Оболочечные классы. Упаковка (boxing) и распаковка (unboxing)
- 3.7.Приоритет операторов
- 3.8.Типы-перечисления (enum)
- Краткие итоги по главе 3
- Задания
- Глава 4. Работа с числами в языке Java
- 4.1 Двоичное представление целых чисел Позиционные и непозиционные системы счисления
- Двоичное представление положительных целых чисел
- Двоичное представление отрицательных целых чисел. Дополнительный код
- Проблемы целочисленной машинной арифметики
- Шестнадцатеричное представление целых чисел и перевод из одной системы счисления в другую
- 4.2. Побитовые маски и сдвиги
- 4.3. Двоичное представление вещественных чисел Двоичные дроби
- Мантисса и порядок числа
- Стандарт ieee 754 представления чисел в формате с плавающей точкой*
- Краткие итоги по главе 4
- Задания
- Глава 5. Управляющие конструкции Составной оператор
- Условный оператор if
- Оператор выбора switch
- Условное выражение …?... : …
- Оператор цикла for
- Оператор цикла while – цикл с предусловием
- Оператор цикла do...While – цикл с постусловием
- Операторы прерывания continue, break, return, System.Exit
- Краткие итоги по главе 5
- Задания
- Глава 6. Начальные сведения об объектном программировании
- Наследование и полиморфизм. Uml-диаграммы
- Функции. Модификаторы. Передача примитивных типов в функции
- Локальные и глобальные переменные. Модификаторы доступа и правила видимости. Ссылка this
- Передача ссылочных типов в функции. Проблема изменения ссылки внутри подпрограммы
- Наследование. Суперклассы и подклассы. Переопределение методов
- Наследование и правила видимости. Зарезервированное слово super
- Статическое и динамическое связывание методов. Полиморфизм
- Базовый класс Object
- Конструкторы. Зарезервированные слова super и this. Блоки инициализации
- Удаление неиспользуемых объектов и метод finalize. Проблема деструкторов для сложно устроенных объектов
- Перегрузка методов
- Правила совместимости ссылочных типов как основа использования полиморфного кода. Приведение и проверка типов
- Рефакторинг
- Reverse engineering – построение uml-диаграмм по разработанным классам
- Краткие итоги по главе 6
- Задания
- Глава 7. Важнейшие объектные типы Массивы
- Коллекции, списки, итераторы
- Работа со строками в Java. Строки как объекты. Классы String, StringBuffer и StringBuilder
- Работа с графикой
- Исключительные ситуации Обработка исключительных ситуаций
- Иерархия исключительных ситуаций
- Объявление типа исключительной ситуации и оператор throw
- Объявление метода, который может возбуждать исключительную ситуацию. Зарезервированное слово throws
- Работа с файлами и папками
- Краткие итоги по главе 7
- Задания
- Глава 8. Наследование: проблемы и альтернативы. Интерфейсы. Композиция Проблемы множественного наследования классов. Интерфейсы
- Отличия интерфейсов от классов. Проблемы наследования интерфейсов
- Пример на использование интерфейсов
- Композиция как альтернатива множественному наследованию
- Краткие итоги по главе 8
- Задания
- Глава 9. Дополнительные элементы объектного программирования на языке Java Потоки выполнения (threads) и синхронизация
- Преимущества и проблемы при работе с потоками выполнения
- Синхронизация по ресурсам и событиям
- Класс Thread и интерфейс Runnable. Создание и запуск потока выполнения
- Поля и методы, заданные в классе Thread
- Подключение внешних библиотек dll.“Родные” (native) методы*
- Краткие итоги по главе 9
- Задания
- Глава 10. Введение в сетевое программирование Краткая справка по языку html
- Апплеты
- Сервлеты
- Технология jsp – Java Server Pages
- Краткие итоги по главе 10
- Задания
- Глава 11. Встроенные классы Виды встроенных классов
- Вложенные (nested) классы и интерфейсы
- Внутренние (inner) классы
- Локальные (local) классы
- Анонимные (anonimous) классы и обработчики событий
- Анонимные (anonimous) классы и слушатели событий (listeners)
- Краткие итоги по главе 11
- Задания
- Глава 12. Компонентное программирование Компонентная архитектура JavaBeans
- Мастер создания компонента в NetBeans
- Пример создания компонента в NetBeans – панель с заголовком
- Добавление в компонент новых свойств
- Добавление в компонент новых событий
- Краткие итоги по главе 12
- Задания
- Литература
- Дополнительная литература
- 276 Курс подготовлен при поддержке Sun Microsystems