У цьому уроці ми розглянемо з вами деякі інструменти, за допомогою яких в Сі-Шарп реалізується поліморфізм - віртуальні методи, перевизначення методів.
Віртуальний метод - це метод, який може бути перевизначений в класі спадкоємця.
Перевизначення методу - це зміна його реалізації в класі спадкоємця. Перевизначивши метод, він буде працювати по-різному в базовому класі і класі спадкоємця, маючи при цьому одне і те ж ім'я і аргументи і тип повернення.
Віртуальний метод оголошується за допомогою ключового слова virtual:
[Модифікатор доступу] virtual [тип] [ім'я методу] ([аргументи])
// тіло методу
>
* Статичний метод не може бути віртуальним.
Оголосивши віртуальний метод, ми тепер можемо перевизначити його в класі спадкоємця. Для цього використовується ключове слово override:
[Модифікатор доступу] override [тип] [ім'я методу] ([аргументи])
// нове тіло методу
>
Розглянемо це на прикладі. У нас є клас Людина. і від нього успадковуються ще два - Студент і Учень. У базовому класі є віртуальний методShowInfo. який виводить інформацію про об'єкт. У класах Студент іУченік цей метод переопределяется для того, щоб до висновку базової інформації додати ще специфічну, що відносяться до відповідного класу:
class Person
public string Name
public int Age
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
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");
>
>
static void Main (string [] args)
List
persons.Add (new Person ( "Василь", 32));
persons.Add (new Student ( "Андрій", 21, "МГУ"));
persons.Add (new Pupil ( "Олена", 12, "7-Б"));
foreach (Person p in persons)
p.ShowInfo ();
У методі 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);
>
Створіть три класи: Воїн, Воін_в_легкіх_доспехах і Воін_в_тяжелих_доспехах. У всіх них є властивість - Колічество_жізней, а також метод Получіть_урон, який приймає в якості аргумент значення одержуваного шкоди. Реалізуйте цей метод по-різному для всіх типів, встановивши різні коефіцієнти залежно від типу обладунків у формулі вирахування здоров'я.
Абстрактні класи, методи і властивості в Сі-Шарп
У цьому уроці ми продовжимо з вами розглядати інструменти поліморфізму. На черзі у нас абстрактні класи, методи і властивості.
Абстрактний клас - це клас оголошений з ключовим словомabstract:
abstract class [ім'я_класу]
// тіло
>
Такий клас має такі особливості:
- не можна створювати екземпляри (об'єкти) абстрактного класу;
- абстрактний клас може містити як абстрактні методи / властивості, так і звичайні;
- в класі спадкоємця повинні бути реалізовані всі абстрактні методи і властивості, оголошені в базовому класі.
Навіщо потрібні абстрактні класи?
У самому по собі абстрактному класі, від якого ніхто не успадковується, сенсу немає, так як не можна створювати його екземпляри. В абстрактному класі зазвичай реалізується деяка загальна частина декількох сутностей або іншими словами - абстрактна сутність, яка, як об'єкт, не може існувати, і ця частина необхідна в класах спадкоємців. Конкретні приклади будуть далі.
Розуміння абстрактних методів не буде для вас складним завданням, якщо ви вже ознайомилися з віртуальними методами.
Абстрактний метод - це метод, який не має своєї реалізації в базовому класі, і він ПОВИНЕН бути реалізований в класі-спадкоємця. Абстрактний метод може бути оголошений лише в абстрактному класі.
Яка ж різниця між віртуальним і абстрактним методом?
- Віртуальний метод може мати свою реалізацію в базовому класі, абстрактний - немає (тіло порожнє);
- Абстрактний метод повинен бути реалізований в класі спадкоємця, віртуальний метод перевизначати необов'язково.
[Модифікатор доступу] abstract [тип] [ім'я методу] ([аргументи]);
Реалізація абстрактного методу в класі спадкоємця відбувається так само, як і перевизначення методу - за допомогою ключового слова override:
[Модифікатор доступу] override [тип] [ім'я методу] ([аргументи])
// реалізація методу
>
Створення абстрактних властивостей не сильно відрізняється від методів:
[Модифікатор доступу] abstract [тип] [ім'я властивості]
Реалізація в класі-спадкоємця:
Як приклад, наведу програму схожу на ту, яка була в попередньому уроці про віртуальних методах, де виводилася інформація про людину / студента / школяра. Зараз вже будуть тварини. Тоді ми могли створити людини без статусу (не студенти, які не школяр), у якого була деяка інформація, а зараз у нас буде абстрактна сущностьЖівотное. об'єкт якої створювати не можна і немає сенсу, так як кожна тварина буде конкретного подцарства - ссавець, риба, птиця:
abstract class Animal
public string Name
public string Type
foreach (Animal animal in animals)
animal.GetInfo ();
У підсумку, ми все так же працює з одним списком тварин, і, викликаючи один метод GetInfo (). ми отримуємо інформацію про відповідному тварину.
При спробі створити об'єкт абстрактного класу ми отримаємо помилку "Can not create an instance of the abstract class or interface 'ConsoleApplication1.Animal'":
Animal animal = new Animal (); // помилка
Створіть абстрактний клас Людина. нехай там буде властивість Ім'я та абстрактний метод СказатьПріветствіе (). від цього класу буде кілька спадкоємців, які представляють національність (російський, українець, американець.). Повинно пулучіться так, що при виклику методаСказатьПріветствіе () виводилося вітання на мові відповідного національності (Привіт, Привіт, Hi.).