NeverGetBurn
@NeverGetBurn

В чем разница между переопределением (override), от перекрытия (new), наследуемого метода?

Доброго времени суток!

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

Вопросы
  1. Как можно визуализировать эти подходы? Override - зачеркиваю и пишу поверх, а New ?
  2. Когда использовать переопределение, а когда перекрытие ?
  3. Как компилятор преобразует код в обоих случаях ? Он по ключевому слову понимает, что нужно перезаписать (override), а что удалить (new) ?

Очень прошу, подкрепите ответ практическим примером (можно из вашего личного опыта). Заранее благодарю за внимание!
  • Вопрос задан
  • 1839 просмотров
Решения вопроса 1
lexxpavlov
@lexxpavlov
Программист, преподаватель
Сначала отвечу на третий вопрос.
Чтобы понять, в чём разница между переопределением и перекрытием, нужно понять, как программа выбирает, какой вариант метода нужно вызвать, в зависимости от реального типа объекта.
Компилятор создаёт таблицу всех виртуальных методов класса (в том числе, переопределённых, потому что они тоже виртуальные) и указывает, в каком типе они обозначены. При вызове виртуального метода берётся реальный тип объекта и выбирается нужный вариант реализации метода.
Если вы указываете в классе-наследнике метод с ключевым словом new, то этот метод перестаёт быть переопределением метода базового класса, и этот метод не добавляется в ту таблицу переопределений. Значит, при вызове метода поиск по типу объекта не найдёт метод, отмеченный new (его же нет в таблице), и попытается найти ближайший метод.
Обратите внимание, что новый перекрываемый метод тоже может быть указан с ключевым методом virtual, то есть, он тоже попадёт в таблицу виртуальных методов, но как бы в другую таблицу, тем самым создавая новую иерархию реализаций.

2. Когда использовать переопределение, а когда перекрытие?
Обычно нужно переопределение, перекрытие редко кому нужно. Если нужна отдельная реализация у конкретного наследника, то (иногда) можно сделать метод с другим именем, и вызывать напрямую, а не через вызов виртуальных методов. Если это всё-таки необходимо (перекрыть метод), то нужно понимать, что вызвать такой метод через ссылку на базовый класс не получится (без приведения к нужному типу).

Интересно, что в Java все методы виртуальные, и нет возможности перекрыть (но не переопределить) базовый метод, как это можно в c#.

1. Как можно визуализировать эти подходы?
Этот вопрос непонятен. В графическом описании иерархии классов? В UML, насколько я помню, виртуальные методы пишутся курсивом. Значит, перекрытый метод будет обычным, не курсивным шрифтом.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы