С# вызывает переопределенные методы подкласса без знания того, что это экземпляр подкласса

У меня есть базовый класс с виртуальным методом и несколько подклассов, которые переопределяют этот метод.

Когда я сталкиваюсь с одним из этих подклассов, я бы хотел вызвать переопределенный метод, но без знания подкласса. Я могу придумать уродливые способы сделать это (проверить значение и бросить его), но похоже, что для этого должен быть язык на языке. Я хочу, чтобы список содержал несколько подклассов в одном списке, иначе я мог бы просто создать список.

EDIT: Исправлен комментарий в коде, который был неправильным, что привело к очень подходящему первому ответу, который я получил:)

Например:

Class Foo
{ public virtual printMe() { Console.Writeline("FOO"); }
}
Class Bar : Foo
{ public override printMe() { Console.Writeline("BAR"); }
}
List<foo> list = new List<foo>();
// then populate this list with various 'Bar' and other overriden Foos
foreach (Foo foo in list)
{ foo.printMe(); // prints FOO.. Would like it to print BAR
}
</foo></foo>
5 ответов

class Foo
{ public virtual void virtualPrintMe() { nonVirtualPrintMe(); } public void nonVirtualPrintMe() { Console.Writeline("FOO"); }
}
class Bar : Foo
{ public override void virtualPrintMe() { Console.Writeline("BAR"); }
}
List<foo> list = new List<foo>();
// then populate this list with various 'Bar' and other overriden Foos
foreach (Foo foo in list)
{ foo.virtualPrintMe(); // prints BAR or FOO foo.nonVirtualPrintMe(); // always prints FOO
}
</foo></foo>


Зачем ему печатать "Foo"? Это не цель виртуальных методов. Все дело в том, что производные классы могут изменить способ работы функции без изменения интерфейса. Объект Foo будет печатать "Foo", а объект Bar напечатает "Bar". Все остальное было бы неправильно.


Чтобы получить нужное поведение в этой ситуации, вы можете удалить виртуальный объект в базовом классе и использовать новый в подклассе.

Однако, как указал Эд Свангрен, зачем вам?


Разве нет решения, в котором вы просто бросаете объект, который хотите вызвать другим:

foo.printMe(); // prints FOO.. Would like it to print BAR

становится

(Foo)foo.printMe(); // foo can be any derived class of Foo.

Или мне не хватает части вопроса?


Используйте модификатор new, чтобы явно скрыть элемент, унаследованный от базового класса. Чтобы скрыть унаследованный элемент, объявите его в производном классе с использованием того же имени и измените его с помощью нового модификатора. Это приведет к точному поведению, которое вы хотите.

Для получения дополнительной информации перейдите сюда: http://geekswithblogs.net/Mohamed/articles/28613.aspx

licensed under cc by-sa 3.0 with attribution.