У цьому уроці ми розглянемо з вами деякі інструменти, за допомогою яких в Сі-шарп реалізується поліморфізм - віртуальні методи, перевизначення методів.
Віртуальний метод - це метод, який може бути перевизначений в класі спадкоємця.
Перевизначення методу - це зміна його реалізації в класі спадкоємця. Перевизначивши метод, він працюватиме по-різному в базовому класі і класі спадкоємця, маючи при цьому одне і те ж ім'я та аргументи і тип повернення.
Віртуальний метод оголошується за допомогою ключового слова virtual:
[модифікатор доступу] virtual [тип] [ім'я методу] ([аргументи])
{
// Тіло методу
}
* Статичний метод не може бути віртуальним.
Оголосивши віртуальний метод, ми тепер можемо перевизначити його в класі спадкоємця. Для цього використовується ключове слово override:
[модифікатор доступу] override [тип] [ім'я методу] ([аргументи])
{
// Нове тіло методу
}
Розглянемо це на прикладі. У нас є клас Людина, і від нього успадковуються ще два - Студент і Учень. У базовому класі є віртуальний метод ShowInfo, який виводить інформацію про об'єкт. У класах Студент і Учень цей метод перевизначається для того, щоб до висновку базової інформації додати ще специфічну, що відноситься до відповідного класу:
class Person
{
public string Name {get; set; }
public int Age {get; set; }
public Person (string name, int age)
{
Name = name;
Age = age;
}
public virtual void ShowInfo () // оголошення віртуального методу
{
Console.WriteLine ("Людина \ nІмя:" + Name + "\ n" + "Вік:" + Age + "\ n");
}
}
class Student: Person
{
public string HighSchoolName {get; set; }
public Student (string name, int age, string hsName)
: Base (name, age)
{
HighSchoolName = hsName;
}
public override void ShowInfo () // перевизначення методу
{
Console.WriteLine ("Студент \ nІмя:" + Name + "\ n" + "Вік:" + Age + "\ n" + "Назва ВНЗ:" + HighSchoolName + "\ n");
}
}
class Pupil: Person
{
public string Form {get; set; }
public Pupil (string name, int age, string form)
: Base (name, age)
{
Form = form;
}
public override void ShowInfo () // перевизначення методу
{
Console.WriteLine ("Учень (ця) \ nІмя:" + Name + "\ n" + "Вік:" + Age + "\ n" + "Клас:" + Form + "\ n");
}
}
class Program
{
static void Main (string [] args)
{
List <Person> persons = new List <Person> ();
persons.Add (new Person ("Василь", 32));
persons.Add (new Student ("Андрій", 21, "МДУ"));
persons.Add (new Pupil ("Олена", 12, "7-Б"));
foreach (Person p in persons)
p.ShowInfo ();
Console.ReadKey ();
}
}
У методі main ми створюємо список людей, в який додаємо просто людей, студента і учня, і далі виводимо інформацію про кожного з них викликом методу ShowInfo (). Результат роботи - висновок інформації відповідно типу об'єкта.
А тепер може виникнути питання - а що буде, якщо прибрати перевизначення, відкинувши ключові слова virtual і override? У такому випадку, в базовому класі і в класі спадкоємця будуть методи з однаковим ім'ям ShowInfo. Програма працювати буде, але про кожен об'єкт, незалежно це просто людина або студент / учень, виводитиметься інформація тільки як про просту людину (буде викликатися метод ShowInfo з базового класу).
Це можна виправити, додавши перевірки на тип об'єкту, і за допомогою приведення типів, викликати потрібний метод ShowInfo:
foreach (Person p in persons)
{
if (p is Student)
((Student) p) .ShowInfo ();
else if (p is Pupil)
((Pupil) p) .ShowInfo ();
else p.ShowInfo ();
}
Тільки от, скільки зайвого коду від цього з'являється. Думаю, стає зрозуміло, що нам дають віртуальні методи і перевизначення.
Виклик базового методу
Буває так, що функціонал методу, який перевизначається, в базовому класі мало відрізняється від функціоналу, який повинен бути визначений в класі спадкоємця. У такому випадку, при перевизначенні, ми можемо викликати спочатку цей метод з базового класу, а далі дописати необхідний функціонал. Це робиться за допомогою ключового слова base:
public virtual void ShowInfo () // ShowInfo в класі Person
{
Console.WriteLine ("Ім'я:" + Name);
Console.WriteLine ("Вік:" + Age);
}
public override void ShowInfo () // ShowInfo в класі Student
{
base.ShowInfo (); // Викликає базовий метод ShowInfo ()
Console.WriteLine ("Назва ВНЗ:" + HighSchoolName);
}
Домашнє завдання
Створіть три класи: Воїн, Воїн_в_легких_досягеннях і Воїн_в_важких_досягненнях. У всіх них є властивість - Кількість_життів, а також метод Отримати_шкоду, який приймає в якості аргументу значення одержуваної шкоди. Реалізуйте цей метод по-різному для всіх типів, встановивши різні коефіцієнти залежно від типу обладунків у формулі вирахування здоров'я.
PS. Не забудьте поділитися з друзями цією статтею за допомогою кнопок соціальних мереж.