Почему виртуальные методы должны быть явно переопределены в C#?Зачем нужно, чтобы виртуальные методы были явно переопределены в C#?
ответ
Объявив метод как virtual
, вы указав свое намерение, что метод может быть переопределен в производном классе.
Объявив свой метод, реализующий в override
, ваш являются , указав свое намерение, что вы перекрытый метод virtual
.
Требование, чтобы ключевое слово override
использовалось для переопределения виртуального метода, разработчики языка поощряют ясность, требуя от вас указать свои намерения.
Поскольку это делает код более читаемым:
class Derived : Base
{
void Foo();
}
В C++, Foo может или не может быть виртуальный метод, мы не можем сказать, глядя на определение. В C# мы знаем, что метод является виртуальным (или нет), потому что есть либо ключевое слово virtual, либо override.
Комментарий Джейсона ниже - лучший ответ.
(отредактированный для ясности)
... и он дает Intellisense возможность помочь нам переопределить метод. Тип «override» и Intellisense всплывает с выбором и даже заполняет всю сигнатуру метода для нас. Как это здорово? – Tergiver
... и, самое главное, это позволяет компилятору рассказать нам, когда мы допустим ошибку (например, если вы добавите параметр в метод базового класса в C++, он разбивает все производные классы, но вы не можете его узнать - причина некоторых очень неприятных для отслеживания ошибок, потому что бит поведения производного класса просто перестает работать. В C# он дает ошибку для каждого переопределения, которое больше не отменяет ничего) –
_ «В C++ это может быть, t скажем, посмотрев определение ». - Посмотрев определение, мы можем сказать, что это вовсе не C++. – stakx
Если вы не добавили ключевое слово override
, метод будет скрыт (как если бы у него было ключевое слово new
), а не переопределено.
Например:
class Base {
public virtual void T() { Console.WriteLine("Base"); }
}
class Derived : Base {
public void T() { Console.WriteLine("Derived"); }
}
Base d = new Derived();
d.T();
Этот код печатает Base
. Если вы добавите override
в адрес Derived
, код будет распечатать Derived
.
Вы не можете сделать это на C++ с помощью виртуального метода. (There is no way to hide a C++ virtual method without overriding it))
Не все виртуальные методы должны быть переопределены, хотя все абстрактные методы должны (и должны) быть. Что касается того, почему ключевое слово override является явным, это потому, что переопределение и скрытие ведут себя по-разному. Метод скрытия не вызывается через ссылку на базовый класс, тогда как переопределенный метод. Вот почему компилятор специально предупреждает о том, как вы должны использовать ключевое слово «новое» в случае, когда вы скрываете, а не переопределяете.
Это потому, что члены команды C# - все опытные программисты на С ++. И знаете, как зарождается эта конкретная ошибка:
class Base {
protected:
virtual void Mumble(int arg) {}
};
class Derived : public Base {
protected:
// Override base class method
void Mumble(long arg) {}
};
Это гораздо более распространено, чем вы могли подумать. Производный класс всегда объявляется в другом файле исходного кода. Обычно вы не ошибаетесь сразу, это происходит, когда вы рефакторинг. Никакой взгляд из компилятора, код работает довольно нормально, просто не делает того, что вы ожидаете от него. Вы можете смотреть на него в течение часа или дня и не видеть ошибку.
Этого никогда не может быть в программе на C#. Даже управляемый C++ применял этот синтаксис, преднамеренно ломаясь с собственным синтаксисом C++. Всегда смелый выбор. IntelliSense снимает лишние формулировки.
В C# есть много синтаксических твинов, которые напоминают синтаксис такого типа.
EDIT: а остальная часть C++ сообщества согласился и принял переопределения ключевое слово в новой C++ 11 спецификации языка.
+1 Лучший ответ IMO, потому что он объясняет «почему» позади решения для дизайна языка, а не «как работают виртуальные вызовы», поскольку более высокие ответы отвечают ... PS. @Hans Я, кажется, натыкаюсь на множество уместных ответов, написанных вами в эти дни :) –
Нет необходимости явно переопределять виртуальный метод в производном классе. Маркировка метода virtual только позволяет переопределить.
- 1. Переопределены только виртуальные методы
- 2. Убедитесь, что все виртуальные методы переопределены
- 3. Зачем нужно, чтобы объекты с копией были скопированы?
- 4. C# виртуальные методы
- 5. виртуальные методы C++
- 6. C++: Виртуальные методы
- 7. C++ следует использовать виртуальные методы?
- 8. Полиморфизм, виртуальные методы, C++
- 9. Чистые виртуальные методы в C#?
- 10. Зачем нужно, чтобы библиотеки были перечислены в приложениях проекта?
- 11. Static_cast и виртуальные методы в C++
- 12. Декораторы и виртуальные методы
- 13. Нужно ли указывать виртуальные методы подклассов?
- 14. Зачем нужно явно указывать при выполнении ОБНОВЛЕНИЯ?
- 15. Зачем реализовать интерфейс явно?
- 16. Зачем вам нужно перегружать методы?
- 17. C++ и виртуальные методы переопределяете
- 18. Шаблоны, наследование и виртуальные методы (C++)
- 19. Не виртуальные методы в Objective-C
- 20. Зачем нужны виртуальные машины?
- 21. Виртуальные методы не действуют виртуальные
- 22. Неопределенная ссылка на таблицу, даже если виртуальные методы были реализованы
- 23. Как схематически представляют переопределены методы
- 24. Зачем использовать виртуальные функции?
- 25. Виртуальные общедоступные методы в ASP C#
- 26. Преимущества объявляя чтобы быть переопределены методы членов в интерфейсе
- 27. Зачем нужны виртуальные деструкторы?
- 28. Виртуальные методы в классах
- 29. Виртуальные методы переопределения объекта
- 30. Виртуальные методы и нарезка объекта в C#
Почему бы не отметить его «абстрактное» и принудительное переопределение? –
@George: Потому что вы можете использовать только абстрактный модификатор в абстрактных классах. –
@George Stocker - Потому что вы можете не захотеть пометить весь свой класс абстрактным (классу нужен абстрактный модификатор, чтобы иметь абстрактные методы). –