Для чего нужно virtual/override?

Недавно ходил на собеседование на позицию .Net разработчика, на собеседовании у меня спросили "Для чего нужен virtual/override?". Я рассказал о том, что помечая метод виртуальным, мы можем в классе наследнике его переопределить и либо добавить свою реализацию к базовой, либо оставить только свою. Далее меня спросили "только для того, чтоб можно было переопределить метод?", я сказал, что в EF для ленивой загрузки данных, в итоге мои ответы не являлись исчерпывающим ответом на вопрос.
Какие еще могут быть ответы?

P.S. я не стал спрашивать у интервьюера правильный ответ, так как были сомнения в его профессионализме
  • Вопрос задан
  • 1129 просмотров
Пригласить эксперта
Ответы на вопрос 3
Deerenaros
@Deerenaros
Программист, математик, задрот и даже чуть инженер
Ахтунг, товарищ. Перед тем как сомневаться в профессионализме своих коллег очень советую хотя бы немного сомневаться в собственном. Это как минимум изредка полезно. А теперь ноги в руки и вперёд читать про таблицы, виртуальность и методы. Это не просто полезно, но архиважно. Учитывая, собственно, вопрос.

А вопрос состоял в следующем. Вот у нас есть объекты, друг от друга наследуются, имплементируются и всё круто-прекрасно, но блджад. Зачем они нужны-то? Нет, не агрегация данных, хотя и она тоже. Нет, не агрегация реализации, хотя и она тоже. И нет, нет, не просто потому что. Хотя и это тоже... А вот подумай о такой ситуации. Есть библиотека. Да не важно какая, ну пусть это будет UI/UX. Вот есть абстрактный (!) класс кнопка. Почему абстрактный? Да потому что любая кнопка - это кнопка. Это как бы класс над классом. Кнопка может быть красной, может быть кликабельной, может становится не кликабельной после нажатия, может открывать диалог выбора файлов, а может закрывать приложение к чертям. В общем, много чего может уметь делать кнопка. И вот эту кнопку хочется поставить на формочку. И сделал создатель библиотеки такой прекрасный метод у формы PutAnyButtonHere(Button btn, Point xy). Но... Чёрт, чувак, мы должны передать объект класса Button, а у нас какой-нибудь наследник MyBestButton : BestAbstractLibraryButton, который наследник той самой Button. И у Button декларирован такой прекрасный метод TimeWhenUserClickOnMe(Point xy, AnotherInfo somethinElse), собственно... Получается, что где-то в недрах той самой библиотеки, когда автор прекрасной UI/UX библиотеки вызывает этот самый метод он должен вызвать НАШУ реализацию, а не реализацию BestAbstractLibraryButton. И уж точно не несуществующую реализацию Button (ибо метод там чисто-виртуальный). Идея виртуальных методов изначально именно в том, что есть особая таблица, которая хранит реализации отдельно, объекты отдельно, но когда мы пытаемся вызывать у объекта виртуальный метод происходит такая магия, которую принято называть поздним связыванием.

А ключевые слова это просто для того, чтобы программист читая чужие полотна кода хоть ну немного имел возможность хоть как-то их понять. Что конкретно хотел программист в конкретной ситуации. И, если в Java все методы по дефолту виртуальные и ничерта не понятно из чужих полотен, хотел здесь программист позднее связывание, или это просто агрегация функционала, то в шарпе данной проблемы "как бы нет", язык порой чрезвычайно многословен на, казалось, такие банальности. Что в итоге изредка, но экономит чёртову тучу времени.

Сухой остаток. Если мы вызываем виртуальный метод у объекта класса наследника некоторого супер-класса имея ссылку типа супер-класса, то вызывается реализация метода наследника. Если мы вызываем не виртуальный метод у объекта класса наследника некоторого супер-класса имея ссылку типа супер-класса, то вызывается реализация метода супер-класса. В остальном поведение тривиальное.

Отсебятина. Не понимая данных вещей невозможно говорить, что принципы объектно-ориентированного программирования были усвоены. Советую прочитать "Философия Java" (вообще там Java скорее как язык для примеров, в общем-то ООП оно и в Африке ООП). Ну и пытаться разобраться в точке зрения любого человека, особенно если его компетенция хоть чем-то подтверждена (например, успешным трудоустройством).
Ответ написан
Комментировать
Duha666
@Duha666
"я не стал спрашивать у интервьюера правильный ответ, так как были сомнения в его профессионализме" - вот это сильно.

Переопределить мы можем и без виртуальных методов.
А они пригодятся, когда у тебя есть ссылка на базовый класс, которая ведет на унаследованный. Тогда при попытке вызова не виртуального метода вызовется метод базового класса. Если он виртуальный, то метод унаследованного.
Ответ написан
Комментировать
abyrkov
@abyrkov
JavaScripter
Ваша ответ, как ни странно, не является исчерпывающим.
virtual/override нужен для того, чтоб менять метод на протяжении всей цепочки классов.
Пример.
У нас есть класс A с виртуальной функцией. Мы создали из него класс B и преопределили там эту функцию. Потом мы создали objA класса A и objB класса B. Потом мы присвоили objA objB и вызвали эту функцию из objA. Вызовется реализация класса B, а не A. А при обычном замещении было бы наоборот. Вот в чем прикол!
Ответ написан
Комментировать
Ваш ответ на вопрос

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

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