Обобщенные интерфейсы. Синтаксис объявления. Реализация обобщенных интерфейсов в классах. Примеры
Перед изучением данной темы рекомендуется ознакомиться со следующей темой:
Содержание
- 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
⇑
Связанные темы
- Обобщения. Основные понятия. Обобщенные классы и структуры
- Обобщенные методы в классах. Синтаксис объявления. Способы вызова
- Обобщенные делегаты
- Упаковка и распаковка. Необходимость применения обобщений
- Ограничения на конструктор, базовый класс и интерфейс
⇑