Виртуальные методы C# переопределяют возвращаемые аргументы типа и метода
Я хочу инициализировать виртуальный метод с точным именем в абстрактном классе.
И в классе, который является методом переопределения наследника таким, что я могу переопределить:
- возвращаемый тип базового метода
- аргументы метода
Чтобы показать вам, что я действительно хочу сделать, вот что:
abstract class A
{
public virtual void Func1() { }
}
class B : A
{
override string Func1(int a, int b)
{
return (a + b).ToString();
}
}
Я знаю, что C# требует использовать возвращаемый тип / args как в базовом классе, но, может быть, в этой ситуации есть какие-то подсказки с ключевым словом new?
5 ответов:
Вы можете только
Я думаю,что в вашей ситуации вы либо захотите создать перегрузки для всех возможных комбинаций, либо создадите один базовый абстрактный метод, который принимает один тип, который может содержать аргументы, которые вы хотите.overrideточное имя и аргументы. Вы можетеnewвсе, что хотите, но это не переопределение-просто скрытие в случае точного совпадения.Пример:
public abstract void Func1( MyArgumentsType input );Теперь производные классы вынуждены переопределять метод, но вы можете передать надежный набор аргументов к методу, который может обрабатывать больше сценариев.
Здесь полиморфизм работает в вашу пользу, так как вы можете передать производные типы аргументов методу с ситуационными свойствами. Конечно, это требует, чтобы метод реализации понимал более производный тип аргумента.
Переопределение метода
Означает изменение виртуальнойреализации наследуемого члена, а не егосигнатуры . Как вы указали, ключевое слово
newскроет реализацию базового класса члена с тем же именем. Однако это только необязательно, взгляните на это
преимущество использования нового ключевого слова в производном члене класса, имеющем то же имя, что и член базового класса
Похоже, что вы хотите добиться поведения, аналогичного методу
ToString, который имеет много разных вкусов для разных типов (например,.ToString()иfloat.ToString("c")).В этом случае различные реализации
Обратите внимание, что в C# тип результата больше учитывается во времени разрешения функции, поэтому вы не можете действительно иметь 2 функции с одинаковым именем и одинаковыми аргументами и ожидать, что одна из них будет "правильно" выбрана. Если оба видны одновременно, вы получите ошибку времени компиляции. Ключевое словоToStringне являются реализациямиObject.ToString, а скорее обычным дополнительным методом на производных объектах, которые разрешаются соответствующим образом на основе аргументов. Все производные классы заканчиваются одним виртуальным методомToString(исходящим из базового класса и потенциально реализуемым в текущем классе) и необязательно другим аналогично именованные методы, которые не являются виртуальными.newПеред методом делает видимым только этот метод для этого класса (и производных от него) и скрывает метод базового класса с той же сигнатурой. К сожалению делаю это в значительной степени гарантирует большую путаницу, когда для вызова этого метода используется переменная базового класса, содержащая производный класс - виртуальный из базового класса будет вызван, несмотря на все усилия скрыть его.
Твой Кант так бы и сделал. Переопределение метода требует наличия точно такой же сигнатуры, которая включает параметры и тип возвращаемого значения. Вы не можете попросить компилятор переопределить метод с различными параметрами и типом возвращаемого значения.
Если вы хотите полиморфное поведение, вам нужно иметь совместимые сигнатуры. В противном случае компилятор не может гарантировать, что искомый метод будет найден полиморфно.
Нет никакого приемлемого способа рассматривать сигнатуры
void Func1()иstring Func1(int a, int b)Как полиморфный. Вы можете обобщить их с помощью параметровoutлямбд внутри, но в любом случае-чтобы воспользоваться полиморфным поведением, вам нужно привести их к одной общей сигнатуре.
Думаю об этом...как это будет работать? Допустим, у вас есть ссылка, статический тип которой
A, а динамический тип -B, следующим образом:Идея переопределения заключается в том, что вы вызываете метод на super/base, и он разрешается в переопределенную реализацию. По этой логике вы должны быть в состоянии, вfoo(B b) { bar(b); } bar(A a) { }bar, вызватьa.Func1()и он должен вызвать метод вB:a.Func1(???)Но здесь это невозможно из-за отсутствия параметров.
Существуют понятия параметр contravariance и возвращаемый тип ковариации; здесь - интересный ответ в SO, со ссылкой на сообщение Эрика Липперта, которое должно быть интересным чтением.