Разница между перегрузкой и переопределением в Java
Основное различие : перегрузка означает наличие двух методов одного и того же класса с одинаковым именем и с разными типами параметров, тогда как переопределение означает наличие двух разных методов в одном классе с одинаковыми типами параметров, но с разными реализациями.
Переопределение и перегрузка методов — это две концепции или техники, используемые в языках программирования Java. Обе концепции позволяют программисту предоставлять разные реализации для методов под одним и тем же именем. В этой статье проводится различие между двумя концепциями программирования.
Перегрузка функций или перегрузка методов позволяет создавать несколько методов под одним и тем же именем, в одном классе, но отличаться друг от друга во входном и выходном типах функции. Это просто определяется как способность одной функции выполнять разные задачи.
При перегрузке реализации метода имеют одно и то же имя, потому что они выполняют похожие задачи. Также перегрузка считается полиморфной по своей природе. Функции, имеющие разные реализации, зависят от указанных типов аргументов. Обычно это связано со статическими языками программирования, которые обеспечивают проверку типов в вызовах функций. Это также считается практичным, поскольку позволяет программисту писать несколько разных методов в одном классе. Однако при перегрузке процессор во время выполнения меняет имя всех перегруженных методов, что может быть проблемой.
Переопределение метода в объектно-ориентированном программировании — это функция, которая позволяет подклассу или дочернему классу предоставлять конкретную реализацию метода, которая уже предоставлена одним из его суперклассов или родительских классов. Реализация в подклассе переопределяет или заменяет реализацию в родительском классе, предоставляя метод с тем же именем, теми же параметрами или сигнатурой и тем же типом возврата, что и метод в родительском классе.
При переопределении метода функции кодируются для выполнения определенных задач в программе. Переопределение зависит от наличия функции базового класса для ее появления. Здесь выполняемая функция определяется объектом, который используется для ее вызова, т.е. если для вызова метода используется объект родительского класса, то будет выполняться функция в родительском классе. Переопределение имеет полиморфный характер; это помогает разрабатывать программы на основе первого неявного параметра, который может быть разрешен во время выполнения. В Java есть несколько языков, позволяющих программисту предотвращать переопределение метода.
Сравнение между перегрузкой и переопределением:
перегрузка
Переопределение
Это означает наличие методов одного и того же класса под одним и тем же именем, но каждый метод имеет разные параметры или одинаковые параметры с разными типами и порядком.
Это означает наличие подкласса с теми же методами под тем же именем и точно таким же типом параметров и тем же типом возврата, что и у суперкласса.
Это означает, что более одного метода имеют одно и то же имя в одном классе, но имеют разные сигнатуры.
Это означает, что метод базового класса переопределяется в производном классе с той же сигнатурой.
Это добавляет или расширяет методы поведения.
Это изменяет существующее поведение метода.
Это полиморфизм времени компиляции.
Это полиморфизм во время выполнения.
Статический метод может быть перегружен.
Статический метод не может быть переопределен.
Это может или не может требовать наследования.
Это всегда требует наследования.
Обычно это связано со статическими языками программ.
Обычно это связано с объектно-ориентированными программами.
Методы имеют разные подписи.
Методы должны иметь одинаковую подпись.
Это быстрее, чем переопределение.
Это медленный по сравнению с перегрузкой.
Для перегрузки не требуется более одного класса.
Требуется как минимум два класса для перегрузки.
Методы могут иметь любой уровень доступа.
Методы имеют одинаковый или широкий уровень доступа.
Как правильно: перегрузка или переопределение?
Чтобы далеко не ходить за примерами я стал искать прямо на сайте ответы по интересующим меня методам 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 внес исправления в свой ответ.
Ошибки в других ответах, надеюсь, также будут исправлены.
Отслеживать
задан 9 фев 2016 в 20:36
203 2 2 серебряных знака 11 11 бронзовых знаков
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
По смыслу — это абсолютно разные вещи.
Перегрузка (Overloading) — это возможность использовать одинаковые имена в пределах одного класса у методов сходных по своей сути, но не реализации,за счет расширения понятия имени метода до сигнатуры. Подробнее в соседнем вопросе
Переопределение (Overriding) — относится к виртуальным и абстрактным методам. Это возможность замены виртуального или реализация абстрактного наследуемого метода базового класса методом производного класса.
class A < virtual void SomeMethod(int par1, double par2) < >//Делаем перегруженный вариант метода для другого набора параметров void SomeMethod(double par1, int par2) <> > class B : A < //Переопределяем унаследованный виртуальный метод override void SomeMethod(int par1, double par2) < >>
UPD
в наследниках или в производных?
тут разночтений нет. Производный класс, класс наследник, а также принятые в Java суб-класс или подкласс, являются синонимами. Также синонимами являются базовый класс, класс предок, супер-класс(java) и над-класс(java).
Дабы не плодить споры: я использую перевод принятый в MSDN. В различных источниках могут использоваться другие варианты перевода. В любом случае, первичным остается смысл оригинальных терминов на английском.
Чем отличается перегрузка от переопределения?
Полиморфизм – соль ООП. Перегрузка (overload) и переопределение (override) – два инструмента достижения полиморфного поведения в Java.
Перегрузкой реализуется ad-hoc-полиморфизм. Это значит «один и тот же» метод может работать с разными параметрами. С технической точки зрения это просто два разных метода, сигнатуры которых имеют одинаковое название, но разный набор параметров. Важно помнить, что для перегрузки не достаточно различий только модификаторов, возвращаемых типов и списков исключений.
Ad-hoc – не совсем настоящий полиморфизм, так как при нём используется раннее, или статическое связывание (early binding, static dispatch). Это значит, что для выбора конкретного варианта метода используется информация о типе переменной, а не объекта в ней лежащего, и происходит это еще при компиляции.
Если в классе объявлены два перегруженных метода, а аргумент в вызове подходит под оба, случится ошибка компиляции. В примере ниже компилятор не может выбрать между вариантами метода println с параметром char[] и со String , так как null может быть и тем и другим.
Переопределение (override) дает полиморфизм подтипов. Это реализация/подмена метода нефинального родительского класса или интерфейса. С помощью этого механизма достигается поведение, когда экземпляр хранится под типом родителя, но реализация методов используется специфичная для этого конкретного подтипа. Пример:
List list = new LinkedList<>();
list.add(“foo“);
Здесь метод add вызывается общий для всех списков, но добавлен будет именно элемент связного списка.
Выбор конкретного метода происходит в последний момент, в процессе работы программы, в зависимости от типа объекта. Это называется позднее или динамическое связывание методов (late binding, dynamic dispatch).
Переопределение имеет непосредственное отношение к принципу подстановки Лисков (LSP): в хорошем объектно-ориентированном коде для вызывающего кода переопределенный метод не должен быть отличим от оригинального.
Переопределенный метод принято снабжать аннотацией @Override . Ее отсутствие допускается, но компиляция не перегружающего метода с такой аннотацией приведет к ошибке.
При переопределении можно сузить набор выбрасываемых исключений или тип результата, и заменить модификатор доступа на менее строгий.
Статические методы нельзя переопределить, можно только перегрузить.
О внутренностях процесса связывания можно почитать в этой статье.
Чем перегрузка методов отличается от переопределения методов
Переопределение и скрытие методов
В этой статье, я расскажу об использовании ключевых слов new и override применительно к методам классов в C#. Я не буду затрагивать все тонкости использования этих ключевых слов в данном контексте, а наоборот, постараюсь донести самые основные моменты в доступной форме. Скажу сразу, что тема настоящей статьи актуальна при условии, что Вы знакомы с основами ООП (объектно-ориентированного программирования). И так, к делу!
Механизмы переопределения и скрытия методов используются при наличии наследования, и то, не в каждой ситуации, а только в тех, когда Вы создаете в производном классе метод, повторяющий метод базового класса (естественно со своей, специфической реализацией, отличающейся от реализации базового). Давайте сначала разберем случай скрытия метода базового класса в производном.
Представьте, что в определенный момент разработки, Вы понимаете, что метод базового класса (а точнее его реализация) в производном (в производный класс, он попал «по наследству»), работает не так как Вы хотите! И тогда, вы решаете создать подобный метод в производном классе, но с доработанной реализацией. Причем, Вы не хотите придумывать для этого метода какое-то новое название. По двум причинам, во-первых, у метода уже отличное название, а во-вторых Вы не хотите, чтобы пользователю класса был доступен «неподходящий» метод, пришедший из базового класса (замену которому Вы и собираетесь разрабатывать). На практике, это может выглядеть примерно так:
//Базовый класс class FirstClass < //Самый важный метод public void DoSomthing() < //Выводим в консоль, что это метод базового класса Console.WriteLine("FirstClass.DoSomething"); >> //Производный класс class SecondClass : FirstClass < //Тот же важнейший метод что и в базовом public new void DoSomthing() < //Но с другой реализацией (выводим в консоль, что это метод производного класса) Console.WriteLine("SecondClass.DoSomething"); >>
Обратите внимание на выделенную строку. Как видите, в производном классе мы тоже объявили метод «DoSomthing», с таким же прототипом, что и в базовом классе. Но есть одна важная деталь, так как мы решили скрыть метод базового класса, заменив его новым методом, мы указали ключевое слово new сразу после модификатора доступа public.
А теперь, давайте разберемся с переопределением методов базового класса в производном. Тут ситуация немного другая, переопределение методов применяется тогда, когда метод базового класса является виртуальным (для чего нужны виртуальные методы, я рассказывал в уроке № 22 базового курса C#). Давайте модифицируем наш базовый класс, сделав его главный метод виртуальным:
//Базовый класс class FirstClass < //Самый важный метод (виртуальный) public virtual void DoSomthing() < //Выводим в консоль, что это метод базового класса Console.WriteLine("FirstClass.DoSomething"); >>
Теперь метод «DoSomthing» стал виртуальным. И тогда, чтобы не скрыть, а переопределить этот метод в производном классе, нужно использовать ключевое слово override, вместо new, как показано в примере ниже:
//Производный класс class SecondClass : FirstClass < //Тот же важнейший метод что и в базовом (переопределенный) public override void DoSomthing() < //Но с другой реализацией (выводим в консоль, что это метод производного класса) Console.WriteLine("SecondClass.DoSomething"); >>
Как видите, всё довольно просто! Да это только основные варианты использования ключевых слов new и override по отношению к методам класса, есть еще ряд нюансов, но на начальном уровне изучения, достаточно и основных моментов. Главное запомнить, что ключевое слово new скрывает метод базового класса (в том числе и виртуальный), а override переопределяет виртуальный метод базового класса.
Добавить комментарий Отменить ответ
Для отправки комментария вам необходимо авторизоваться.