Учебник по С# | Виртуальные и переопределяющие методы
Задача: создать класс персонажей с методом виртуального недопустимого перемещения.
Краткое содержание
Полиморфизм означает множество форм. В коде полиморфизм позволяет производным классам модифицировать (виртуальные) методы в базовом классе. Все это возможно при использовании виртуальных методов в базовом классе и переопределенииих в производных классах. Это полезно, поскольку вместо создания уникальных имен методов и логики для каждого дочернего объекта. Вместо этого мы можем использовать один метод в базовом классе, изменить метод для каждого отдельного объекта и вызвать метод базового класса.
Пример сценария
Например, базовый класс персонажа с методом для недопустимых ходов. Этот метод по своей основе устанавливает правила того, что считается недопустимым для всех персонажей, но предположим, что у зомби есть определенный шаблон движения, и мы хотим добавить дополнительные ограничения на то, что считается незаконным движением. Без полиморфизма мы должны создать еще один метод Illegal Move Zombie Method с новыми правилами.
Это может быть проблемой, когда у нас много персонажей со своими собственными наборами движений, потому что, когда нам нужно определить тип символ, прежде чем вызывать этот недопустимый ход, и убедитесь, что мы вызываем правильный метод.
foreach (Character monster in character) { if (monster is Skeleton) { Skeleton temp = (Skeleton) monster; temp.IllegalMovesSkeleton(); } if (monster is Zombie) { Zombie temp = (Zombie)monster; temp.IllegalMovesZombie(); } monster.IllegalMoves(); }
Как видите, это может быть очень грязно! Например, мне нужно было проверять монстра по отдельности, корректно приводить его и запускать его метод в цикле for-each.
List<Character> character = new List<Character>(); character.Add(new Zombie()); character.Add(new Skeleton()); foreach (Character monster in character) { if (monster is Skeleton) { Skeleton temp = (Skeleton) monster; temp.IllegalMovesSkeleton(); } if (monster is Zombie) { Zombie temp = (Zombie)monster; temp.IllegalMovesZombie(); } monster.IllegalMoves(); } public class Character { public void IllegalMoves() => Console.WriteLine("OUT OF BOUNDS"); } public class Zombie: Character { public void IllegalMovesZombie() { base.IllegalMoves(); Console.WriteLine("ZOMBIES CANT WALK FOWARD"); } } public class Skeleton : Character { public void IllegalMovesSkeleton() { base.IllegalMoves(); Console.WriteLine("SKELETONS CANT WALK DIAGONALLY"); } }
Сила полиморфизма
С полиморфизмом у нас может быть один метод, который мы можем модифицировать.
foreach (Character monster in character) monster.IllegalMoves();
Поскольку этот метод находится в базовом классе, все объекты, производные от класса символов, могут вызывать метод недопустимых перемещений, и нам все равно если это скелетилизомби, потому что мы можем переопределить этот метод.
List<Character> character = new List<Character>(); character.Add(new Zombie()); character.Add(new Skeleton()); foreach (Character monster in character) monster.IllegalMoves(); public class Character { public virtual void IllegalMoves() => Console.WriteLine("OUT OF BOUNDS"); } public class Zombie: Character { public override void IllegalMoves() { base.IllegalMoves(); Console.WriteLine("ZOMBIES CANT WALK FOWARD"); } } public class Skeleton : Character { public override void IllegalMoves() { base.IllegalMoves(); Console.WriteLine("SKELETONS CANT WALK DIAGONALLY"); } }
В заключение, используя KEYWORDS:
public class Character { public virtual void IllegalMoves() => Console.WriteLine("OUT OF BOUNDS"); }
- Виртуальный в базовом классе позволяет производным (дочерним) классам изменять метод с помощью ключевого слова override.
public class Zombie: Character { public override void IllegalMoves() { base.IllegalMoves(); Console.WriteLine("ZOMBIES CANT WALK FOWARD"); } } public class Skeleton : Character { public override void IllegalMoves() { base.IllegalMoves(); Console.WriteLine("SKELETONS CANT WALK DIAGONALLY"); } }
- Методы переопределения в производном классе должны использовать одно и то же имя, параметры и тип возвращаемого значения. Вы также можете использовать ключевое слово base для вызова исходного метода из базового (родительского) класса.
Конечно, полиморфизм — это еще не все. Например, мы также можем создавать абстрактные и интерфейсные методы для принудительного применения конкретных методов, но это тема для другого разговора!