Узагальнені інтерфейси. Синтаксис оголошення. Реалізація узагальнених інтерфейсів у класах. Приклади
Перед вивченням даної теми рекомендується ознайомитись з наступною темою:
Зміст
- 1. Синтаксис оголошення узагальненого інтерфейсу
- 2. Приклади реалізації узагальненого інтерфейсу для одиночного типу T
- 3. Приклад реалізації в класі узагальненого інтерфейсу для двох типів T1, T2
- Зв’язані теми
Пошук на інших ресурсах:
1. Синтаксис оголошення узагальненого інтерфейсу
У мові C# допускається оголошувати узагальнені інтерфейси. При оголошенні узагальненого інтерфейсу сигнатура методів, що оголошені в інтерфейсі, може містити посилання на параметризовані типи. Перелік параметризованих типів (наприклад, T1, T2, …, TN) задається в заголовку оголошення інтерфейсу між символами <>.
Загальна форма оголошення узагальненого інтерфейсу наступна:
interface InterfaceName<T1, T2, ..., TN> { // ... }
тут
- InterfaceName – ім’я інтерфейсу;
- T1, T2, TN – імена типів, які виступають в якості параметрів інтерфейсу.
Клас, що реалізує інтерфейс InterfaceName<T1, T2, …, TN> повинен оголошуватись наступним чином:
class ClassName<T1, T2, ..., TN> : InterfaceName<T1, T2, ..., TN> { // ... }
тут
- ClassName – ім’я класу, що реалізує інтерфейс InterfaceName.
У найбільш простішому випадку інтерфейс отримує деякий тип T. У цьому випадку загальна форма оголошення інтерфейсу та його реалізації в класі має вигляд
interface InterfaceName<T> { // ... } class ClassName<T> : InterfaceName<T> { // ... }
⇑
2. Приклади реалізації узагальненого інтерфейсу для одиночного типу T
2.1. Реалізація основних операцій над числами: додавання, віднімання
У прикладі оголошується узагальнений інтерфейс, який отримує параметром тип T. В інтерфейсі реалізовані основні операції додавання та віднімання чисел.
using System; namespace ConsoleApp19 { // Інтерфейс, що отримує параметр типу T interface Operations<T> { // Оголошення методів, які використовують тип T double Add(T var1, T var2); double Sub(T var1, T var2); } // Клас, що реалізує інтерфейс MyInterface<T1, T2> class MyClass<T> : Operations<T> { // Реалізація методу, що використовує тип T public double Add(T var1, T var2) { double res = Convert.ToDouble(var1) + Convert.ToDouble(var2); return res; } public double Sub(T var1, T var2) { double res = Convert.ToDouble(var1) + Convert.ToDouble(var2); return res; } } class Program { static void Main(string[] args) { // Демонстрація використання узагальненого інтерфейсу // 1. Для типу-заповнювача int MyClass<int> mc1 = new MyClass<int>(); double res1 = mc1.Add(23, 48); Console.WriteLine("res1 = {0}", res1); // 2. Для типу-заповнювача float MyClass<float> mc2 = new MyClass<float>(); double res2 = mc2.Sub(8.804f, 1.704f); Console.WriteLine("res2 = {0:f}", res2); Console.ReadKey(); } } }
Результат виконання програми
res1 = 71 res2 = 10.51
⇑
2.2. Реалізація методів обробки масиву даних
Оголосити узагальнений інтерфейс IItems<T>, що містить наступні методи обробки масиву даних типу T:
- Count() – повертає кількість елементів у масиві;
- GetValue() – отримати елемент за його індексом;
- SetValue() – встановити новий елемент в заданому індексі;
- AddValue() – додати елемент в кінець масиву;
- Delete() – видалити елемент з заданої позиції.
Оголосити узагальнений клас ArrayItems<T>, який реалізує інтерфейс IItems<T>. Крім методів інтерфейсу у класі додатково реалізувати:
- масив даних типу T[];
- конструктор без параметрів;
- конструктор з параметром, який отримує інший масив типу T[];
- метод Print(), що виводить масив у зручній для перегляду формі.
Текст програми, що розв’язує дану задачу наступний:
using System; namespace ConsoleApp19 { // Узагальнений інтерфейс для масиву елементів різних типів interface IItems<T> { // Кількість елементів у масиві int Count(); // Отримати елемент за його індексом T GetValue(int index); // Встановити новий елемент в заданому індексі void SetValue(T value, int index); // Додати елемент в кінець масиву void AddValue(T value); // Видалити елемент з позиції index void Delete(int index); } // Клас, що реалізує інтерфейс IItems<T> class ArrayItems<T> : IItems<T> { // Внутрішній масив T[] items; // Конструктори public ArrayItems() { // Встановити значення за замовчуванням items = default(T[]); } public ArrayItems(T[] _items) { items = _items; } // Метод, що повертає кількість елементів у масиві public int Count() { return items.Length; } // Отримати елемент за його індексом public T GetValue(int index) { return items[index]; } // Встановити нове значення за індексом public void SetValue(T value, int index) { // Перевірка, чи індекс в допустимих межах if ((index>=0)&&(index<items.Length)) items[index] = value; } // Додати елемент в кінець масиву public void AddValue(T value) { // Запам'ятати посилання на старий масив T[] items2 = items; // Створити новий масив items = new T[items.Length + 1]; // items2 => items for (int i = 0; i < items.Length - 1; i++) items[i] = items2[i]; // Додати останній елемент items[items.Length - 1] = value; } // Видалити елемент з позиції index public void Delete(int index) { // Перевірка, чи коректний index if ((index < 0) || (index >= items.Length)) return; // Створити новий масив з довжиною на 1 менше T[] items2 = new T[items.Length - 1]; // Скопіювати елементи оминаючи позицію index for (int i = 0; i < index; i++) items2[i] = items[i]; for (int i = index + 1; i < items.Length; i++) items2[i - 1] = items[i]; // Перенаправити внутрішнє посилання items = items2; } // Вивід масиву на екран public void Print(string message) { Console.Write(message + "\t\t"); for (int i = 0; i < items.Length; i++) Console.Write("{0} ", items[i]); Console.WriteLine(); } } class Program { static void Main(string[] args) { // Демонстрація роботи класу ArrayItems<T> для типу int int[] AI = { 2, 8, 3, 4, 11, 17, 5 }; ArrayItems<int> A1 = new ArrayItems<int>(AI); A1.Print("A1:"); // Додати елемент A1.AddValue(130); A1.Print("A1 + [130]:"); // Видалити другий елемент A1.Delete(1); A1.Print("A1 - A1[1]:"); // Замінити третій елемент A1.SetValue(111, 2); A1.Print("A1[2] = 111: "); // Зчитати елемент з індексом 4 int item = A1.GetValue(4); Console.WriteLine("A1[4] = {0}", item); Console.ReadKey(); } } }
Результат виконання програми
A1: 2 8 3 4 11 17 5 A1 + [130]: 2 8 3 4 11 17 5 130 A1 - A1[1]: 2 3 4 11 17 5 130 A1[2] = 111: 2 3 111 11 17 5 130 A1[4] = 17
⇑
3. Приклад реалізації в класі узагальненого інтерфейсу для двох типів T1, T2
Оголошується інтерфейс MyInterface, що містить методи виведення даних типів T1, T2. У класі MyClass<T1, T2>, який реалізує цей інтерфейс, продемонстровано:
- реалізацію методів інтерфейсу MyInterface<T1, T2>;
- доступ до даних типів T1, T2.
using System; namespace ConsoleApp19 { // Інтерфейс, що отримує два параметри типу T1, T2 interface MyInterface<T1, T2> { // Оголошення методів, які використовують типи T1, T2 void Print1(T1 var1); void Print2(T2 var2); } // Клас, що реалізує інтерфейс MyInterface<T1, T2> class MyClass<T1, T2> : MyInterface<T1, T2> { // Реалізація методу, що використовує тип T1 public void Print1(T1 var1) { Console.WriteLine("var1 = {0}", var1); } // Реалізація методу, що використовує тип T2 public void Print2(T2 var2) { Console.WriteLine("var2 = {0}", var2); } } class Program { static void Main(string[] args) { // 1. Оголосити екземпляр класу з типами-заповнювачами int, string MyClass<int, string> mc1 = new MyClass<int, string>(); mc1.Print1(233); mc1.Print2("Hello world!"); // 2. Оголосити екземпляр класу з типами-заповнювачами double, char MyClass<double, char> mc2 = new MyClass<double, char>(); mc2.Print1(8.77); mc2.Print2('z'); // 3. Реалізація для типів long, long MyClass<long, long> mc3 = new MyClass<long, long>(); mc3.Print1(32323L); mc3.Print2(30000L); Console.ReadKey(); } } }
Результат виконання програми
var1 = 233 var2 = Hello world! var1 = 8.77 var2 = z var1 = 32323 var2 = 30000
⇑
Зв’язані теми
- Узагальнення. Основні поняття. Узагальнені класи та структури
- Узагальнені методи в класах. Синтаксис оголошення. Способи виклику
- Узагальнені делегати
- Упакування та розпакування. Необхідність застосування узагальнень
- Обмеження на конструктор, базовий клас та інтерфейс
⇑