Перевизначення віртуальних методів в узагальнених класах. Приклади
Перед вивченням даної теми рекомендується ознайомитись з наступними темами:
- Ієрархії узагальнених класів. Узагальнений базовий та похідний класи
- Поліморфізм. Пізнє та раннє зв’язування. Приклади. Передача в метод посилання на базовий клас. Ключові слова virtual, override, new
Зміст
- 1. Перевизначення віртуальних методів в узагальнених класах. Особливості. Синтаксис
- 2. Приклад, що демонструє перевизначення методів в узагальнених класах, що утворюють ієрархію. Класи отримують параметром тип T
- 3. Приклад перевизначення віртуальних методів для базового та похідного класів, що отримують параметрами два типи T1, T2
- Споріднені теми
Пошук на інших ресурсах:
1. Перевизначення віртуальних методів в узагальнених класах. Особливості. Синтаксис
Віртуальні методи в узагальнених класах можуть бути перевизначені. Технологія перевизначення методів в узагальненнях працює так само як в неузагальнених класах. Більш детально про перевизначення методів у класах описується тут.
Метод, що оголошується в базовому класі як віртуальний, повинен бути оголошений з модифікатором virtual. Однойменні методи в успадкованих класах оголошуються з модифікатором override.
В свою чергу, успадковані класи можуть бути базовими для інших класів. У цьому випадку, ланцюг модифікаторів override продовжується.
Якщо не потрібно, щоб метод у похідному класі перевизначав метод базового класу та розглядався як невіртуальний (не підтримує механізм поліморфізму), то такий метод оголошується з модифікатором new або без модифікатора.
Якщо два узагальнені класи, що отримують параметром тип T, утворюють ієрархію, то загальна форма оголошення віртуального методу в базовому класі наступна
class Base<T> { ... public virtual VirtualMethodName(parameters) { ... } ... }
Щоб забезпечити механізм поліморфізму, у похідному класі однойменний метод оголошується з ключовим словом override.
class Derived<T> : Base<T> { ... public override VirtualMethodName(parameters) { ... } ... }
⇑
2. Приклад, що демонструє перевизначення методів в узагальнених класах, що утворюють ієрархію. Класи отримують параметром тип T
Даний приклад демонструє спосіб перевизначення однойменного методу в похідному класі у випадку двох класів.
Оголошується базовий узагальнений клас Base<T>, який отримує параметром тип T і має наступні складові:
- поле value узагальненого типу T, що визначає дані класу;
- конструктор з одним параметром;
- віртуальні методи доступу GetValue(), SetValue(). Ці методи оголошуються з модифікатором virtual;
- віртуальний метод PrintValue(), який виводить значення внутрішнього поля value.
Також оголошується узагальнений клас Derived<T>, що успадкований від класу Base<T>. Клас містить наступні поля та методи:
- внутрішнє поле value узагальненого типу T;
- конструктор, що викликає конструктор базового класу;
- віртуальні методи GetValue(), SetValue(), які перевизначають однойменні методи класу Base<T>. Ці методи оголошені з ключовим словом override;
- віртуальний метод PrintValue(), який перевизначає однойменний метод базового класу. Метод оголошується з модифікатором virtual.
using System; namespace ConsoleApp1 { class Base<T> { // Внутрішні дані T value; // Конструктор public Base(T _value) { Console.WriteLine("Constructor Base(T)"); value = _value; } // Методи доступу до value - віртуальні public virtual T GetValue() { Console.WriteLine("Base.GetValue()"); return value; } public virtual void SetValue(T _value) { Console.WriteLine("Base.SetValue()"); value = _value; } // Віртуальний метод, що виводить значення value // з класу Base public virtual void PrintValue(string message) { Console.WriteLine(message); Console.WriteLine("Base.value = " + value); } } // Похідний клас, який має власні методи, // імена яких співпадають з іменами базового класу Base<T> class Derived<T> : Base<T> { // Внутрішнє поле з іменем value T value; // Конструктор, обов'язково повинен // викликати конструктор базового класу public Derived(T valueBase, T valueDerived) : base(valueBase) { Console.WriteLine("Constructor Derived(T)"); value = valueDerived; } // Методи доступу - перевизначають методи доступу базового класу public override T GetValue() { Console.WriteLine("Derived.GetValue()"); return value; } public override void SetValue(T _value) { Console.WriteLine("Derived.SetValue()"); value = _value; } // Метод, що перевизначає віртуальний метод базового класу public override void PrintValue(string message) { base.PrintValue(message); Console.WriteLine("Derived.value = " + value); } } class Program { static void Main(string[] args) { // 1. Створити екземпляр базового класу Base<double> obj1 = new Base<double>(2.88); obj1.PrintValue("obj1:"); // Викликати методи базового класу obj1.SetValue(11.77); Console.WriteLine("value = " + obj1.GetValue()); Console.WriteLine("--------------------"); // 2. Створити екземпляр похідного класу Derived<int> obj2 = new Derived<int>(10, 20); obj2.PrintValue("obj2:"); // Викликати методи похідного класу obj2.SetValue(35); obj2.PrintValue("obj2:"); Console.ReadKey(); } } }
Результат виконання програми
Constructor Base(T) obj1: Base.value = 2.88 Base.SetValue() Base.GetValue() value = 11.77 -------------------- Constructor Base(T) Constructor Derived(T) obj2: Base.value = 10 Derived.value = 20 Derived.SetValue() obj2: Base.value = 10 Derived.value = 35
⇑
3. Приклад перевизначення віртуальних методів для базового та похідного класів, що отримують параметрами два типи T1, T2
У прикладі продемонстровано:
- використання механізму спадковості для оголошення узагальнених класів, що утворюють ієрархію;
- оголошення базового та похідного узагальнених класів, які отримують параметрами два типи T1, T2;
- виклик конструктору базового класу з успадкованого класу у випадку узагальнень;
- перевизначення віртуальних методів базового класу з метою забезпечення поліморфізму;
- звертання до полів базового класу з успадкованого класу з допомогою засобу base.
Оголошується два узагальнені класи, які отримують параметрами типи T1, T2. Класи утворюють ієрархію. Один з класів є базовий, інший – похідний (успадкований).
Узагальнений базовий клас A<T1, T2> містить наступні елементи:
- внутрішні поля a1, a2, що мають відповідно типи T1, T2;
- конструктор з двома параметрами, який ініціалізує значеннями поля a1, a2;
- віртуальні методи читання полів a1, a2 з іменами GetA1(), GetA2(). Ці методи оголошено з модифікатором virtual;
- методи запису нових значень в поля a1, a2 з іменами SetA1(), SetA2(). Ці методи оголошено з модифікатором virtual.
З класу A<T1, T2> успадкований клас B<T1, T2>, який не містить внутрішніх полів, а містить наступні методи:
- конструктор з двома параметрами. Даний конструктор викликає конструктор базового класу з допомогою ключового слова base;
- віртуальні методи для читання значень полів a1, a2 базового класу. Методи мають такі самі назви як методи базового класу: GetA1(), GetA2(). Це означає, що вони перевизначають методи базового класу. Для забезпечення поліморфізму методи оголошено з ключовим словом override. У методах здійснюється виклик однойменних методів базового класу з допомогою ключового слова base;
- віртуальні методи SetA1(), SetA2() для запису нових значень в поля a1, a2 базового класу. Робота методів у класі аналогічна методам GetA1(), GetA2().
Нижче наведено текст демонстраційної програми
using System; namespace ConsoleApp1 { class A<T1, T2> { // Внутрішні дані T1 a1; T2 a2; // Конструктор public A(T1 _a1, T2 _a2) { a1 = _a1; a2 = _a2; } // Методи доступу до a1, a2 public virtual T1 GetA1() { return a1; } public virtual T2 GetA2() { return a2; } public virtual void SetA1(T1 a1) { this.a1 = a1; } public virtual void SetA2(T2 a2) { this.a2 = a2; } } // Похідний клас, який має власні методи, // імена яких співпадають з іменами базового класу A<T1, T2> class B<T1, T2> : A<T1,T2> { // Конструктор, обов'язково повинен // викликати конструктор базового класу public B(T1 a1, T2 a2) : base(a1, a2) { } // Методи доступу - перевизначають методи доступу базового класу, // ключове слово override дозволяє використовувати механізм поліморфізму. public override T1 GetA1() { // Викликати метод базового класу return base.GetA1(); } public override T2 GetA2() { // Викликати метод базового класу return base.GetA2(); } public override void SetA1(T1 a1) { // Викликати метод базового класу base.SetA1(a1); } public override void SetA2(T2 a2) { // Викликати метод базового класу base.SetA2(a2); } } class Program { static void Main(string[] args) { // 1. Створити екземпляр базового класу A<double, int> obj1 = new A<double, int>(2.55, 13); // Вивести дані з obj1 Console.WriteLine("obj1.a1 = " + obj1.GetA1()); Console.WriteLine("obj1.a2 = " + obj1.GetA2()); // 2. Створити екземпляр похідного класу B<float, char> obj2 = new B<float, char>(3.8f, 'X'); // Вивести дані з obj2 Console.WriteLine("obj2.a1 = " + obj2.GetA1()); Console.WriteLine("obj2.a2 = " + obj2.GetA2()); // Змінити дані в obj2 obj2.SetA1(100.05f); obj2.SetA2('$'); Console.WriteLine("The data in the object has been changed."); Console.WriteLine("obj2.a1 = " + obj2.GetA1()); Console.WriteLine("obj2.a2 = " + obj2.GetA2()); Console.ReadKey(); } } }
Результат виконання програми
obj1.a1 = 2.55 obj1.a2 = 13 obj2.a1 = 3.8 obj2.a2 = X The data in the object has been changed. obj2.a1 = 100.05 obj2.a2 = $
⇑
Споріднені теми
- Поліморфізм. Пізнє та раннє зв’язування. Приклади. Передача в метод посилання на базовий клас. Ключові слова virtual, override, new
- Узагальнення. Основні поняття. Узагальнені класи та структури
- Ієрархії узагальнених класів. Узагальнений базовий та похідний класи
⇑