Хотите знать, в чем разница между следующим:
Случай 1: Базовый класс
public void DoIt();
Случай 1: Унаследованный класс
public new void DoIt();
Случай 2: Базовый класс
public virtual void DoIt();
Случай 2: Унаследованный класс
public override void DoIt();
Оба случая 1 и 2, по-видимому, имеют одинаковый эффект в зависимости от проведенных тестов. Есть ли разница или предпочтительный способ?
c#
inheritance
overriding
new-operator
Шираз Бхайджи
источник
источник
Ответы:
позвонит,
Derived.DoIt
если это отменяетBase.DoIt
.Сначала позвоню
Base.DoIt
, потомDerived.DoIt
. По сути, это два совершенно отдельных метода, которые имеют одно и то же имя, а не производный метод, переопределяющий базовый метод.Источник: блог Microsoft
источник
This indicates for the compiler to use the last defined implementation of a method
, как найти последнюю определенную реализацию метода ??override
метод, когда базовый класс определяет метод какvirtual
. Словоvirtual
является базовым классом говоря : «Эй, когда я называю этот метод, он мог бы фактически был заменен производной реализацией, так что я не знаю заранее , какой метод реализации я на самом деле вызова во время выполнения. Такvirtual
Значит есть заполнитель для метода. Это подразумевает, что методы, которые не помечены как,virtual
не могут быть переопределены. Но вы можете заменить любой не виртуальный метод в производном классе модификаторомnew
, доступным только на производном уровне.виртуальный : указывает, что метод может быть переопределен наследником
переопределить : переопределяет функциональность виртуального метода в базовом классе, предоставляя другую функциональность.
new : скрывает оригинальный метод (который не должен быть виртуальным), предоставляя другую функциональность. Это следует использовать только там, где это абсолютно необходимо.
Когда вы скрываете метод, вы все равно можете получить доступ к исходному методу путем приведения к базовому классу. Это полезно в некоторых сценариях, но опасно.
источник
override
и / илиnew
безvirtual
родительского метода?В первом случае вы скрываете определение в родительском классе. Это означает, что он будет вызываться только тогда, когда вы имеете дело с объектом как дочерним классом. Если вы приведете класс к его родительскому типу, будет вызван родительский метод. Во втором случае метод переопределяется и будет вызываться независимо от того, был ли объект приведен как дочерний или родительский класс.
источник
попробуйте следующее: (case1)
Редактировать: virtual + override разрешается во время выполнения (поэтому переопределение действительно переопределяет виртуальные методы), в то время как new просто создает новый метод с тем же именем и скрывает старый, он разрешается во время компиляции -> ваш компилятор вызовет метод it ' видит
источник
В случае 1, если вы использовали вызов метода DoIt () унаследованного класса, а тип объявлен как базовый класс, вы увидите действие базового класса даже.
источник
Разница между этими двумя случаями заключается в том, что в случае 1 базовый
DoIt
метод не переопределяется, а просто скрывается. Это означает, что в зависимости от типа переменной зависит, какой метод будет вызван. Например:Это может привести к путанице и привести к непредвиденному поведению, и его следует избегать, если это возможно. Таким образом, предпочтительным способом будет случай 2.
источник
Мой способ запомнить оба ключевых слова, чтобы они были противоположны друг другу.
override
:virtual
ключевое слово должно быть определено для переопределения метода. Метод, использующийoverride
ключевое слово, которое независимо от типа ссылки (ссылка на базовый класс или производный класс), если оно создается с помощью базового класса, запускает метод базового класса. В противном случае метод производного класса запускается.new
: если ключевое слово используется методом, в отличие отoverride
ключевого слова, тип ссылки важен. Если он создан с производным классом, а ссылочный тип является базовым классом, выполняется метод базового класса. Если он создается с производным классом, а ссылочный тип является производным классом, выполняется метод производного класса. А именно, это контрастoverride
ключевого слова. Если вы забудете или не добавите новое ключевое слово в метод, компилятор будет работать по умолчанию, так какnew
используется ключевое слово.Звоните в основном:
Вывод:
Новый пример кода,
Играйте с кодом, комментируя по одному.
источник
Если ключевое слово
override
используется в производном классе, то оно переопределяет родительский метод.Если ключевое слово
new
используется в производном классе, тогда производный метод скрывается родительским методом.источник
У меня был тот же вопрос, и это действительно сбивает с толку, вы должны учитывать, что переопределение и новые ключевые слова работают только с объектами базового типа и значения производного класса. Только в этом случае вы увидите эффект переопределения и нового: так что если у вас есть
class A
иB
,B
наследует отA
, то вы создаете экземпляр объекта следующим образом:Теперь при вызове методов будет учитываться его состояние. Переопределить : означает, что он расширяет функцию метода, затем он использует метод в производном классе, тогда как новый сообщает компилятору скрыть метод в производном классе и использовать метод в базовом классе. Вот очень хороший взгляд на эту тему:
https://msdn.microsoft.com/EN-US/library/ms173153%28v=VS.140,d=hv.2%29.aspx?f=255&MSPPError=-2147217396
источник
Статья ниже на vb.net, но я думаю, что объяснение новых переопределений очень легко понять.
https://www.codeproject.com/articles/17477/the-dark-shadow-of-overrides
В какой-то момент в статье есть это предложение:
Принятый ответ на этот вопрос идеален, но я думаю, что в этой статье представлены хорошие примеры, чтобы лучше понять различия между этими двумя ключевыми словами.
источник
Из всех этих новых - самое запутанное. Посредством экспериментов новое ключевое слово похоже на предоставление разработчикам возможности переопределить реализацию наследуемого класса реализацией базового класса путем явного определения типа. Это как думать иначе.
В приведенном ниже примере результат будет возвращать «Производный результат» до тех пор, пока тип явно не будет определен как тест BaseClass, только тогда будет возвращен «Базовый результат».
источник
Функциональная разница не будет показана в следующих тестах:
В этом примере Doit, который вызывается, - это тот, которого вы ожидаете вызвать.
Чтобы увидеть разницу, вы должны сделать это:
Вы увидите , если вы запустите этот тест , что в случае 1 (как вы определили его), то
DoIt()
вBaseClass
называется, в случае 2 (как вы определили его), тоDoIt()
вDerivedClass
называется.источник
В первом случае он вызовет метод производного класса DoIt (), поскольку новое ключевое слово скрывает метод базового класса DoIt ().
Во втором случае он будет вызывать переопределение DoIt ()
давайте создадим экземпляр этих классов
Все ожидается наверху. Позволяет установить instanceB и instanceC в instanceA, вызвать метод DoIt () и проверить результат.
источник
Все комбинации none, virtual, override, new и abstract:
источник