Чем перегрузка методов отличается от переопределения методов

от admin

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

Переопределение (overriding) и перегрузка (overloading) – одни из ключевых понятий в программировании на Java. Эти механизмы позволяют реализовать полиморфизм в программах Java. Полиморфизм — одна из концепций ООП.

На этом скриншоте показано, где в коде Java происходит перегрузка, а где – переопределение.

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

Перегрузка и переопределение: сравнительный анализ

Переопределение Перегрузка
Реализует «полиморфизм времени выполнения» Реализует «полиморфизм времени компиляции»
Вызов метода определяется во время выполнения на основе типа объекта. Вызов метода определяется во время компиляции
Происходит между суперклассом и подклассом Происходит между методами в рамках одного класса
Одинаковая сигнатура (имя и аргументы метода) Одинаковое имя, но разные параметры
В случае возникновения ошибки эффект будет виден во время выполнения Ошибка может быть обнаружена во время компиляции.

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

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

Переопределение

Метод process() и параметры int i, int j в Processor переопределяются дочерним классом MathProcessor. Обратите внимание на строки 7 и 23:

Метод process() и int[] ints в Processor также переопределяются в дочернем классе. Смотрите строки 11 и 28.

Перегрузка

Метод process() перегружается в классе Processor. Об этом говорят строки 7, 11 и 15:

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

Java. Наследование. Переопределение и перегрузка унаследованных методов. Полиморфизм. Динамическая диспетчеризация методов

Переопределение метода – это случай, когда подкласс и суперкласс содержат методы, которые имеют одинаковое имя и сигнатуру типов (рисунок 1). Переопределение метода возникает в случаях, когда классы образовывают иерархию наследования.

Java. Наследование. Пример переопределения метода суперкласса A в подклассе B

Рисунок 1. Пример переопределения метода method() суперкласса A в подклассе B

На рисунке 1 класс B наследует (расширяет) класс A . Класс A есть суперклассом для класса B . В подклассе B объявляется метод с таким же именем как и в суперклассе A . Итак, в данном случае, метод с именем method() суперкласса A есть переопределенным в подклассе B .

2. Какое отличие между переопределением и перегрузкой метода?

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

  • при переопределении методы суперкласса и подкласса носят одинаковое имя и одинаковую сигнатуру типов параметров (см. рис. 1 );
  • при перегрузке методы суперкласса и подкласса носят одинаковое имя но разные сигнатуры типов параметров. На рисунке 2 продемонстрирована перегрузка метода в иерархии наследования.

Java. Наследование. Пример перегрузки метода в классах A, B, C которые образовывают иерархию

Рисунок 2. Пример перегрузки метода с именем method() в классах A , B , C которые образовывают иерархию

На рисунке 2 изображены 3 класса с именами A , B , C которые образуют иерархию наследования. Класс B наследует класс A . Класс C наследует класс B . Во всех классах реализованы разные методы, которые имеют одинаковое имя method() . Параметры метода в каждом классе отличаются. Это означает, что метод method() есть перегруженым.

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

Если в суперклассе и подклассе реализованы методы, которые носят одинаковое имя и сигнатуру типов параметров, то действует следующее правило:

  • метод из подкласса переопределяет метод суперкласса.

На рисунке 3 схематически изображено правило взаимодействия между одноименными методами суперкласса и подкласса.

Java. Наследование. Переопределение метода суперкласса в методе подкласса

Рисунок 3. Демонстрация переопределения метода суперкласса в методе подкласса

На рисунке 3 изображен пример переопределения метода суперкласса в подклассе. Объявляется 3 класса с именами A , B , C . В каждом классе реализован метод с именем method() без параметров. Этот метод имеет одинаковую сигнатуру во всех классах.

Каждый объект (экземпляр) класса вызывает метод класса на который он был объявлен. Из экземпляра objB вызывается метод method() который реализован в классе B . Из экземпляра objC вызывается метод method() , который реализован в классе C .

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

Результат выполнения программы

4. Получение доступа из метода подкласса к методу суперкласса в случае, когда совпадают имена методов и сигнатуры их параметров. Ключевое слово super . Пример

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

На рисунке 4 изображен доступ к методу суперкласса A из подкласса B . В подклассе B есть метод с таким же именем и списком параметров, поэтому, этот метод переопределяет метод суперкласса. Чтобы доступиться к методу суперкласса A в методе подкласса B используется ключевое слово super .

Java. Наследование. Вызов метода суперкласса из метода подкласса с помощью ключевого слова super

Рисунок 4. Вызов метода суперкласса из метода подкласса с помощью ключевого слова super

Текст программы, которая демонстрирует рисунок 4 следующий

Результат выполнения программы

5. Пример, который демонстрирует перегрузку методов в классах, которые образовывают иерархию наследования

Если классы образовывают иерархию путем наследования, то в этих классах имена методов могут совпадать.

Метод считается перегруженным (не переопределенным) в случае, если:

  • в разных классах существует метод с таким же именем;
  • сигнатура параметров метода в каждом классе отличается.

Таким образом, методы с разными сигнатурами считаются перегруженными а не переопределенными.

На рисунке 5 изображен пример перегрузки метода с именем method() . Объявляются три класса с именами A , B , C которые образовывают иерархию. В классе A метод с именем method() реализован без параметров. В классе B метод с именем method() реализован с одним параметром типа int . В классе C метод с именем method() реализован с одним параметром типа double .

Читать:
Как скопировать файлы из разных папок в одну

Java. Наследование. Перегрузка метода в классах, которые образовывают иерархию

Рисунок 5. Перегрузка метода с именем method() в классах, которые образовывают иерархию

Текст программы, которая демонстрирует рисунок 5 следующий

Результат работы программы

6. Что такое динамическая диспетчеризация методов? Пример реализации полиморфизма в Java

Динамическая диспетчеризация методов есть один из наиболее эффективных принципов объектно-ориентированного программирования.

Динамическая диспетчеризация методов – это специальный механизм, который позволяет вызвать переопределенный метод в процессе выполнения программы а не во время компиляции. Динамическая диспетчеризация методов важна при реализации полиморфизма.

Рисунок 6 демонстрирует динамическую диспетчеризацию методов. Реализованы 3 класса с именами A , B , C которые образуют иерархию. В каждом классе реализован метод с именем method() . Сигнатура метода во всех классах одинаковая.

Java. Наследование. Динамическая диспетчеризация методов для трех классов

Рисунок 6. Демонстрация динамической диспетчеризации методов для трех классов, которые образуют иерархию

В начале кода демонстрации (рисунок 6) объявляется ссылка refA на базовый класс A

Теперь этой ссылке можно присваивать значение ссылки на подкласс класса A .

Таким образом, с помощью ссылки refA можно вызвать методы экземпляров классов A , B , C которые образуют иерархию. Если refA ссылается на экземпляр класса A , то строка

будет вызывать метод с именем method() класса A .

Аналогично, если ссылка refA ссылается на экземпляр (объект) класса B , то

будет вызывать соответствующий метод класса B .

Вышесказанное касается и класса C .

Как видно из рисунка 6, соответствующий вариант метода method() определяется типом объекта, на который ссылается ссылка refA , а не типом этой ссылки в момент ее объявления.

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

Результат выполнения программы

7. Пример, демонстрирующий способы реализации полиморфизма (динамической диспетчеризации методов)

Полиморфизм может быть реализован в программах двумя способами:

  • при присваивании ( = ) ссылке на базовый класс экземпляра любого производного класса. В этом случае, с помощью ссылки (через символ ‘ . ‘) вызывается переопределенный метод того экземпляра, на который в данный момент указывает эта ссылка;
  • при реализации некоторого метода, который получает параметром ссылку на базовый класс. В этом случае, в теле метода вызывается переопределенный метод по ссылке (метод, имеет общее имя и сигнатуру во всех классах иерархии). От того, на экземпляр какого класса указывает ссылка, зависит какой именно переопределенный метод будет вызван.

Нижеследующий пример демонстрирует эти два случая на примере иерархии из трех классов A , B , C . Все классы имеют метод Print() без параметров.

Как правильно: перегрузка или переопределение?

В одних статьях пишут перегрузка, в других пишут переопределение. Тоже самое с наследниками и производными. По смыслу это одно и то же, но как правильно:

  • перегрузка или переопределение?
  • в наследниках или в производных?

Чтобы далеко не ходить за примерами я стал искать прямо на сайте ответы по интересующим меня методам Equals и OnModelCreating, которые описаны в документации как виртуальные, и нашел следующие ответы:

  • «следует перегрузить метод OnModelCreating — и написать там примерно следующее»
    27 май ’15 в 15:53, Pavel Mayorov, 9,255
  • «базовый класс всех типов-значений, перегружает метод Equals»
    30 сен ’15 в 0:01, VladD, 74k
  • «Переопределите Equals так, чтобы он сравнивал два экземпляра»
    23 дек ’15 в 8:52, PashaPash, 20.1k

Из контекста следует, что в ответах говорят о виртуальных методах.
Получается, что перегрузка и переопределение — это одно и тоже.
Хотелось бы понять как правильно: перегрузка или переопределение?

UPD: (2/10/2016 8:52 PM)

Перегрузка и переопределение, как сказал rdom: это абсолютно разные вещи.
VladD внес исправления в свой ответ.
Ошибки в других ответах, надеюсь, также будут исправлены.

По смыслу — это абсолютно разные вещи.

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

Переопределение (Overriding) — относится к виртуальным и абстрактным методам. Это возможность замены виртуального или реализация абстрактного наследуемого метода базового класса методом производного класса.

UPD

в наследниках или в производных?

тут разночтений нет. Производный класс, класс наследник, а также принятые в Java суб-класс или подкласс, являются синонимами. Также синонимами являются базовый класс, класс предок, супер-класс(java) и над-класс(java).

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

Кофе-брейк #139. Перегрузка и переопределение в Java. 5 методов Java, о которых вы не знали

Кофе-брейк #139. Перегрузка и переопределение в Java. 5 методов Java, о которых вы не знали - 1

Источник: Medium Благодаря этой статье вы узнаете о методах переопределения (Overriding) и перегрузки (Overloading) в языке Java. Из-за того, что оба этих термина часто путают между собой, стоит четко понимать предназначение каждого метода и варианты их применения.

Перегрузка (Overloading)

Переопределение (Overriding)

5 методов Java, о которых вы не знали

1. decrementExact

2. getAsDouble

3. absExact

4. endsWith

5. divideUnisgned

Заключение

decrementExact — уменьшает/вычитает заданное число на 1

getAsDouble — часть функции OptionalDouble , возвращает число с двойным значением или указывает на его отсутствие

absExact — возвращает абсолютное значение числа, если оно может быть представлено как исходный тип данных

endsWith() — возвращает логическое значение в зависимости от того, существует ли указанный суффикс в данной строке

divideUnsigned() — выполняет обычное деление, возвращает результат деления числа

Похожие статьи