На этом шаге мы рассмотрим задание и использование ообщенных интерфейсов.
Интерфейс также может быть обобщенным. Класс, который создается путем реализации обобщенного интерфейса, может быть либо обобщенным, либо обычным. Следующий пример иллюстрирует эту ситуацию.
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace pr260_1 { // Обобщенный интерфейс: interface MyInterface<X, Y> { void set(X a, Y b); void show(); } // Обобщенный класс реализует обобщенный интерфейс: class Alpha<X, Y>: MyInterface<X, Y> { private X first; private Y second; public void set(X a, Y b) { first = a; second = b; } public void show() { Console.WriteLine("Поля {0} и {1}", first, second); } } // Обобщенный класс реализует обобщенный интерфейс: class Bravo<Y>: MyInterface<int, Y> { private int first; private Y second; public void set(int a, Y b) { first = a; second = b; } public void show() { Console.WriteLine("Поля {0} и {1}", first, second); } } // Обычный класс реализует обобщенный интерфейс: class Charlie: MyInterface<int, char> { private int first; private char second; public void set(int a, char b) { first = a; second = b; } public void show() { Console.WriteLine("Поля {0} и {1}", first, second); } } // Главный класс: class Program { // Главный метод: static void Main() { Console.WriteLine("Первый объект"); // Создание объекта на основе обобщенного класса: Alpha <string, double> A = new Alpha<string, double>(); // Использование интерфейсной переменной: MyInterface<string, double> Ra = A; // Вызов методов: A.set("Alpha", 100.0); Ra.show(); Ra.set("alpha", 150.0); A.show(); Console.WriteLine("Bтopoй объект"); // Создание объекта на основе обобщенного класса: Bravo<string> B = new Bravo<string>(); // Использование интерфейсной переменной: MyInterface <int, string> Rb = B; // Вызов методов: B.set(200, "Bravo"); Rb.show(); Rb.set(250, "bravo"); B.show(); Console.WriteLine("Третий объект"); // Создание объекта на основе обычного класса: Charlie C = new Charlie(); // Использование интерфейсной переменной: MyInterface<int, char> Rc = C; // Вызов методов: C.set(300, 'C'); Rc.show(); Rc.set(350, 'D'); C.show(); // Задержка: Console.ReadLine(); } } }
Результат выполнения программы представлен ниже:
Рис.1. Результат работы приложения
Мы описали обобщенный интерфейс MyInterface с двумя обобщенными параметрами X и Y. В интерфейсе объявлены два метода. Метод set() не возвращает результат, и у него два аргумента обобщенных типов. Метод show() не возвращает результат, и у него нет аргументов. Любой класс, реализующий интерфейс MyInterface, должен содержать описание этих методов.
Также мы описываем три класса, реализующих интерфейс MyInterface. Класс Alpha является обобщенным с двумя обобщенными параметрами X и Y. Класс реализует интерфейс с теми же параметрами (соответствующая инструкция в описании класса имеет вид MyInterface<X, Y>). В классе есть два закрытых поля first и second обобщенных типов, метод set(), предназначенный для присваивания значений полям, а также метод show(), отображающий значение полей в консольном окне.
Класс Bravo также является обобщенным, и у него только один обобщенный параметр (обозначен как Y). В классе реализуется интерфейс MyInterface, но для первого обобщенного параметра для этого интерфейса указано значение int. Соответственно, инструкция, определяющая реализуемый интерфейс, имеет вид MyInterface<int, Y>. Класс Bravo описан подобно классу Alpha, но только одно поле относится к типу int, а второе поле относится к обобщенному типу. Соответствующим образом описан и метод set().
Класс Charlie является обычным (не обобщенным). Он реализует версию обобщенного интерфейса MyInterface, но с явно указанными значениями int и char для обобщенных параметров.
В главном методе программы создаются объекты классов Alpha, Bravo и Charlie. Кроме этого, объявляются интерфейсные переменные, которым в качестве значения присваиваются ссылки на соответствующие объекты. При объявлении интерфейсных переменных указываются имя интерфейса и в угловых скобках значения обобщенных параметров. Значения обобщенных параметров, указанные при объявлении интерфейсных переменных, должны соответствовать значениям обобщенных параметров, использованных при создании объекта.
На следующем шаге мы рассмотрим обощенные классы и наследование.