Подскажите, пожалуйста, почему вызов метода с модификатором new не является полиморфным, а с модификаторами virtual/override является?
Вопрос на понимание теории, поэтому постараюсь ответить просто, но понятно.
Полиморфизм - это одинаковое, по своей сути, поведение, но реализуемое поразному.
В C# принцип полиморфизма реализуется с помощью виртуальных методов и переопределения (override
) их в наследниках.
new
предназначен для тех случаев, когда мы не можем менять код базового класса, а нужный нам метод не является виртуальным и его поведение нам не подходит. Иными словами: когда нельзя, но очень хочется. Такой метод не является полиморфным просто потому, что он не является частью общего интерфейса базового класса. Это просто какой-то другой метод класса наследника, не имеющий ни какого отношения к базовому классу, но мы очень хотим, чтобы у него была сигнатура как у одного из методов базового класса.
Примеры тут, разумеется, уже были, но пусть уж будет все в одном месте.
Возьмем для примера птиц, все птицы имеют название и могут перемещаться в пространстве, поэтому мы можем создать такой базовый класс:
abstract class Bird
{
public virtual string Name => "Птица";
public void Move() { Console.WriteLine($"{Name} летит"); }
}
Свойство Name сразу сделали виртуальным, ведь название то у каждой птички свое, а метод Move оставили обычным, большинство ведь летает, а у исключений перекроем потом, делов-то.
Теперь мы хотим разнообразить наш зоопарк и заводим производные классы переопределив свойство Name
class Eagle : Bird
{
public override string Name => "Орёл";
}
class Ostrich : Bird
{
public override string Name => "Страус";
//и тут вспоминаем, что страус не летает, а бегает
new void Move() { Console.WriteLine($"{Name} бежит"); }
}
class Penguin : Bird
{
public override string Name => "Пингвин";
//а пингвин и бегает с трудом, зато плавает
new void Move() { Console.WriteLine($"{Name} плывет"); }
}
Вроде все хорошо, все учли. Собираем зоопарк в кучу:
Bird[] birds = {new Eagle(), new Ostrich(), new Penguin()};
И выводим на прогулку:
foreach(Bird b in birds)
{
b.Move();
}
и выясняем интересный факт, с именами все нормально, но внезапно все научились летать:
Вывод в консоль в результате выполнения цикла:
Орёл летит
Страус летит
Пингвин летит
Name
у нас было виртуальным, поэтому работает полиморфизм и несмотря на то, что переменная у нас базового класса Bird, получаем то, что хотели получить - у каждой птички свое имя.
Move
не был виртуальным, мы просто скрыли его базовую реализацию под новым методом класса-наследника. В этом случае полиморфизм не работает и при обращении через переменную базового класса вызывается базовая реализация метода. Поэтому сами по себе страусы у нас как положено бегают, пингвины плавают, а в компании с другими птицами могут и полетать, даже если крылья вообще не предусмотрены природой, как у Киви. =)
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Излазил уже просторы интернета, но до сих пор не понял как правильно обновить datagridview Что делаю не так?
подскажите пожалуйста, ради эксперимента в качестве Item ListBox использую вместо шаблона UserControl который связан в словаре ресурсов с моделью представления...
Хочу сохранять пароли в базе с помощью RSAЯ так понял по примеру - https://msdn