На этом шаге мы рассмотрим особенности реализации такого наследования.
Один интерфейс может наследовать другой интерфейс или даже несколько интерфейсов. Технически наследование интерфейсов реализуется так: в описании интерфейса, наследующего другие интерфейсы, после его имени через двоеточие указываются наследуемые интерфейсы. Общий шаблон наследования интерфейсов выглядит следующим образом:
interface имя: интерфейс1, интерфейс2, ..., интерфейсN { // Тело интерфейса }
Если интерфейс Alpha наследует интерфейс Bravo, то все, что объявлено в интерфейсе Bravo, автоматически включается в состав интерфейса Alpha. Поэтому если некоторый класс MyClass реализует интерфейс Alpha, который наследует интерфейс Bravo, то фактически в этом классе должно быть описано все, что явно объявлено в интерфейсе Alpha, и все, что описано в интерфейсе Bravo (поскольку содержимое интерфейса Bravo по факту содержится и в интерфейсе Alpha).
Программа, в которой используется наследование интерфейсов, представлена ниже. Это еще одна вариация на тему примеров из последних двух шагов (для сокращения объема программного кода некоторые комментарии удалены).
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace pr159_1 { // Первый интерфейс: interface First { // Свойство: int number { get; set; } // Индексатор: int this[int k]{ get; } } // Второй интерфейс: interface Second { // Методы: void setNum(int n); int getNum(); } // Интерфейс наследует другие интерфейсы: interface MyInterface: First, Second { // Метод: void show(); } // Класс реализует интерфейс: class MyClass: MyInterface { private int num; public MyClass(int n) { number = n; show(); } public void show() { Console.WriteLine("Свойство number = " + number); } public void setNum(int n) { num = n; } public int getNum() { return num; } public int number{ get { return getNum(); } set { setNum(value); } } public int this[int k]{ get { int r = number; for(int i = 0; i < k; i++) { r /= 10; } return r % 10; } } } // Класс с главным методом: class Program { static void Main() { int m = 9; MyClass obj = new MyClass(12345); for (int i = 0; i <= m; i++) { Console.Write("|" + obj[m - i]); } Console.WriteLine("|"); // Задержка: Console.ReadLine(); } } }
Результат выполнения программы такой же, как и в предыдущих случаях:
Рис.1. Результат выполнения программы
Описание класса MyClass не изменилось (как и команды в главном методе). Класс MyClass реализует интерфейс MyInterface. Но только теперь сам интерфейс MyInterface наследует интерфейсы First и Second. В интерфейсе First объявлено свойство number и индексатор. В интерфейсе Second объявлены методы setNum() и getNum(). Непосредственно в интерфейсе MyInterface объявлен метод show(). Но поскольку интерфейс MyInterface наследует интерфейсы First и Second, то содержимое этих интерфейсов "незримо присутствует" в интерфейсе MyInterface. Поэтому класс, реализующий интерфейс MyInterface, должен содержать описание не только тех методов, свойств и индексаторов, которые объявлены непосредственно в интерфейсе MyInterface, но и описание всего, что объявлено в интерфейсах, наследуемых в интерфейсе MyInterface.
На следующем шаге мы рассмотрим интерфейсные переменные.