NeverGetBurn
@NeverGetBurn

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

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

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

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

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

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

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

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

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

Войти через центр авторизации
Похожие вопросы
ТатАИСЭнерго Казань
от 40 000 до 60 000 руб.
Аскон Санкт-Петербург
от 130 000 до 180 000 руб.
от 150 000 руб.