Когда мы создаем класс, который наследуется от абстрактного класса, и когда мы реализуем унаследованный абстрактный класс, почему мы должны использовать ключевое слово override?
public abstract class Person
{
public Person()
{
}
protected virtual void Greet()
{
// code
}
protected abstract void SayHello();
}
public class Employee : Person
{
protected override void SayHello() // Why is override keyword necessary here?
{
throw new NotImplementedException();
}
protected override void Greet()
{
base.Greet();
}
}
Поскольку метод объявлен как абстрактный в его родительском классе, он не имеет никакой реализации в родительском классе, так почему здесь необходимо переопределение ключевого слова?
new
ключевое слово` ... Вы также получите ошибку« метод не переопределяет метод базового класса ».Ответы:
"Почему?" На подобные вопросы трудно ответить, потому что они расплывчаты. Я буду считать , что ваш вопрос «какие аргументы могут быть сделаны во время разработки языка , чтобы отстаивать позицию , что
override
это ключевое слово требуется ?»Давайте начнем с шага назад. В некоторых языках, например, Java, методы являются виртуальными по умолчанию и переопределяются автоматически. Разработчики C # знали об этом и считали это незначительным недостатком Java. C # - это не «Java с удаленными глупыми частями», как говорили некоторые, но разработчики C # стремились извлечь уроки из проблемных аспектов проектирования C, C ++ и Java, а не копировать их в C #.
Разработчики C # считали переопределение возможным источником ошибок; в конце концов, это способ изменить поведение существующего, протестированного кода , и это опасно. Переопределение не является чем-то, что должно быть сделано случайно или случайно; это должно быть разработано кем-то, думающим об этом . Вот почему методы не являются виртуальными по умолчанию, и поэтому вы должны сказать, что вы переопределяете метод.
Это основные рассуждения. Теперь мы можем перейти к более сложным рассуждениям.
Ответ StriplingWarrior дает хороший первый аргумент в пользу более продвинутых аргументов. Автор производного класса может не знать о базовом классе, возможно, намеревается создать новый метод, и мы не должны позволять пользователю переопределять по ошибке .
Хотя это обоснованно, существует ряд контраргументов, таких как:
Давайте тогда сделаем еще более продвинутый аргумент по этому вопросу. При каких обстоятельствах автора производного класса можно извинить за то, что он не знает, что делает базовый класс? Хорошо, рассмотрим этот сценарий:
Мы хотим, чтобы автор D был проинформирован о том, что что-то важное изменилось . Что изменилось, так это то, что M теперь является требованием и что их реализация должна быть перегружена. DM может понадобиться изменить свое поведение, как только мы узнаем, что его можно вызывать из базового класса. Правильно не молча сказать: «О, ДМ существует и расширяет БМ». Правильная вещь для компилятора - сбой , и скажите «эй, автор D, проверь свое предположение, которое больше не действует, и исправь свой код, если необходимо».
В вашем примере, предположим , что
override
было необязательно на ,SayHello
потому что это переопределение абстрактный метод. Есть две возможности: (1) автор кода намеревается переопределить абстрактный метод, или (2) переопределяющий метод переопределяется случайно, потому что кто-то еще изменил базовый класс, и код теперь каким-то тонким образом неверен. Мы не можем отличить эти возможности, еслиoverride
это необязательно .Но если
override
это требуется , то мы можем сказать друг от друга три сценария. Если в кодеoverride
есть возможная ошибка, то она отсутствует . Если он намеренно переопределение , тоoverride
есть присутствует . И если оно намеренно не переопределено, тоnew
оно присутствует . Дизайн C # позволяет нам сделать эти тонкие различия.Помните, что сообщение об ошибке компилятора требует чтения мыслей разработчика ; компилятор должен вывести из неправильного кода, какой правильный код, скорее всего, имел в виду автор , и выдать ошибку, указывающую на правильное направление. Чем больше подсказок мы можем заставить разработчика оставить в коде о том, о чем они думали, тем лучше работа компилятора по составлению отчетов об ошибках и, следовательно, тем быстрее вы сможете найти и исправить свои ошибки.
Но в целом, C # был разработан для мира, в котором меняется код . На самом деле очень много возможностей C #, которые кажутся «странными», потому что они информируют разработчика, когда предположение, которое раньше было действительным , стало недействительным, потому что изменился базовый класс. Этот класс ошибок называется «хрупкие сбои базового класса», и в C # есть ряд интересных мер для этого класса сбоев.
источник
Он указывает, пытаетесь ли вы переопределить другой метод в родительском классе или создать новую реализацию, уникальную для этого уровня иерархии классов. Вполне возможно, что программист может не знать о существовании метода в родительском классе с точно такой же сигнатурой, что и у создаваемого им класса, что может привести к неприятным сюрпризам.
Хотя это правда, что абстрактный метод должен быть переопределен в неабстрактном дочернем классе, создатели C #, вероятно, чувствовали, что все же лучше четко указывать, что вы пытаетесь сделать.
источник
Поскольку
abstract
метод является виртуальным методом без реализации, согласно спецификации языка C # , это означает, что абстрактный метод неявно является виртуальным методом. Иoverride
используется для расширения или изменения абстрактной или виртуальной реализации, как вы можете видеть здесьЧтобы перефразировать это немного - вы используете виртуальные методы для реализации некоторого позднего связывания, тогда как абстрактные методы вынуждают подклассы типа явно переопределять метод. В том-то и дело, что когда метод есть
virtual
, он может быть переопределен, когда онabstract
- он должен быть переопределенисточник
Чтобы добавить ответ @ StriplingWarrior, я думаю, что также было сделано, чтобы синтаксис соответствовал переопределению виртуального метода в базовом классе.
Таким образом, C # можно было бы спроектировать так, чтобы вам не требовалось ключевое слово override для переопределения абстрактных методов, но я думаю, что дизайнеры решили, что это будет сбивать с толку, поскольку это не будет соответствовать переопределению виртуального метода.
источник
override
? Я думаю, что большинство людей согласится с тем, что абсурдно заставлять автора D вносить ненужные изменения в коде; их класс в порядке!