Полное руководство. С# 4.0
Шрифт:
В приведенном ниже примере программы демонстрируется применение интер фейсной ссылки. В этой программе переменная ссылки на интерфейс используется с целью вызвать методы для объектов обоих классов — ByTwos и Primes. Для ясности в данном примере показаны все части программы, собранные в единый файл. // Продемонстрировать интерфейсные ссылки. using System; // Определить интерфейс. public interface ISeries { int GetNext; // возвратить следующее по порядку число void Reset; // перезапустить void SetStart(int х); // задать начальное значение } // Использовать интерфейс ISeries для реализации процесса // генерирования последовательного ряда чисел, в котором каждое // последующее число на два больше предыдущего. class ByTwos : ISeries { int start; int val; public ByTwos { start = 0; val = 0; } public int GetNext { val += 2; return val; } public void Reset { val = start; } public void SetStart(int x) { start = x; val = start; } } //
Вот к какому результату приводит выполнение этой программы: Следующее четное число равно 2 Следующее простое число равно 3 Следующее четное число равно 4 Следующее простое число равно 5 Следующее четное число равно 6 Следующее простое число равно 7 Следующее четное число равно 8 Следующее простое число равно 11 Следующее четное число равно 10 Следующее простое число равно 13
В методе Main переменная ob объявляется для ссылки на интерфейс ISeries. Это означает, что в ней могут храниться ссылки на объект любого класса, реализующе го интерфейс ISeries. В данном случае она служит для ссылки на объекты twoOb и primeOb классов ByTwos и Primes соответственно, в которых реализован интерфейс ISeries.
И еще одно замечание: переменной ссылки на интерфейс доступны только методы, объявленные в ее интерфейсе. Поэтому интерфейсную ссылку нельзя использовать для доступа к любым другим переменным и методам, которые не поддерживаются объек том класса, реализующего данный интерфейс. Интерфейсные свойства
Аналогично методам, свойства указываются в интерфейсе вообще без тела. Ниже приведена общая форма объявления интерфейсного свойства. // Интерфейсное свойство тип имя{ get; set; }
Очевидно, что в определении интерфейсных свойств, доступных только для чтения или только для записи, должен присутствовать единственный аксессор: get или set соответственно.
Несмотря на то что объявление свойства в интерфейсе очень похоже на объявление автоматически реализуемого свойства в классе, между ними все же имеется отличие. При объявлении в интерфейсе свойство не становится автоматически реализуемым. В этом случае указывается только имя и тип свойства, а его реализация предоставляет ся каждому реализующему классу. Кроме того, при объявлении свойства в интерфейсе не разрешается указывать модификаторы доступа для аксессоров. Например, аксессор set не может быть указан в интерфейсе как private.
Ниже в качестве примера приведен переделанный вариант интерфейса ISeries и класса ByTwos, в котором свойство Next используется для получения и установки следующего по порядку числа, которое больше предыдущего на два. // Использовать свойство в интерфейсе. using System; public interface ISeries { // Интерфейсное свойство. int Next { get; // возвратить следующее по порядку число set; // установить следующее число } } // Реализовать интерфейс ISeries. class ByTwos : ISeries { int val; public ByTwos { val = 0; } // Получить или установить значение. public int Next { get { val += 2; return val; } set { val = value; } } } // Продемонстрировать применение интерфейсного свойства. class SeriesDemo3 { static void Main { ByTwos ob = new ByTwos; // Получить доступ к последовательному ряду чисел с помощью свойства. for(int i=0; i < 5; i++) Console.WriteLine("Следующее число равно " + ob.Next); Console.WriteLine("\nНачать с числа 21"); ob.Next = 21; for(int i=0; i < 5; i++) Console.WriteLine("Следующее число равно " + ob.Next); } }
При выполнении этого кода получается следующий результат. Следующее число равно 2 Следующее
В интерфейсе можно также указывать индексаторы. Ниже приведена общая форма объявления интерфейсного индексатора. // Интерфейсный индексатор тип_элемента this[int индекс]{ get; set; }
Как и прежде, в объявлении интерфейсных индексаторов, доступных только для чтения или только для записи, должен присутствовать единственный аксессор: get или set соответственно.
Ниже в качестве примера приведен еще один вариант реализации интерфейса ISeries, в котором добавлен индексатор только для чтения, возвращающий i-й эле мент числового ряда. // Добавить индексатор в интерфейс. using System; public interface ISeries { // Интерфейсное свойство. int Next { get; // возвратить следующее по порядку число set; // установить следующее число } // Интерфейсный индексатор. int this[int index] { get; // возвратить указанное в ряду число } } // Реализовать интерфейс ISeries. class ByTwos : ISeries { int val; public ByTwos { val = 0; } // Получить или установить значение с помощью свойства. public int Next { get { val += 2; return val; } set { val = value; } } // Получить значение по индексу. public int this[int index] { get { val = 0; for(int i=0; i < index; i++) val += 2; return val; } } } // Продемонстрировать применение интерфейсного индексатора. class SeriesDemo4 { static void Main { ByTwos ob = new ByTwos; // Получить доступ к последовательному ряду чисел с помощью свойства. for(int i=0; i < 5; i++) Console.WriteLine("Следующее число равно " + ob.Next); Console.WriteLine("\nНачать с числа 21"); ob.Next = 21; for (int i=0; i < 5; i++) Console.WriteLine("Следующее число равно " + ob.Next); Console.WriteLine("\nСбросить в 0"); ob.Next = 0; // Получить доступ к последовательному ряду чисел с помощью индексатора for(int i=0; i < 5; i++) Console.WriteLine("Следующее число равно " + ob[i]); } }
Вот к какому результату приводит выполнение этого кода. Следующее число равно 2 Следующее число равно 4 Следующее число равно 6 Следующее число равно 8 Следующее число равно 10 Начать с числа 21 Следующее число равно 23 Следующее число равно 25 Следующее число равно 27 Следующее число равно 29 Следующее число равно 31 Сбросить в 0 Следующее число равно 0 Следующее число равно 2 Следующее число равно 4 Следующее число равно 6 Следующее число равно 8 Наследование интерфейсов
Один интерфейс может наследовать другой. Синтаксис наследования интерфейсов такой же, как и у классов. Когда в классе реализуется один интерфейс, наследующий другой, в нем должны быть реализованы все члены, определенные в цепочке наследо вания интерфейсов, как в приведенном ниже примере. // Пример наследования интерфейсов. using System; public interface IA { void Meth1; void Meth2; } // В базовый интерфейс включены методы Meth1 и Meth2. // а в производный интерфейс добавлен еще один метод — Meth3. public interface IB : IA { void Meth3; } // В этом классе должны быть реализованы все методы интерфейсов IA и IB. class MyClass : IB { public void Methl { Console.WriteLine("Реализовать метод Meth1."); } public void Meth2 { Console.WriteLine("Реализовать метод Meth2."); } public void Meth3 { Console.WriteLine("Реализовать метод Meth3."); } } class IFExtend { static void Main { MyClass ob = new MyClass; ob.Meth1; ob.Meth2; ob.Meth3; } }
Ради интереса попробуйте удалить реализацию метода Meth1 из класса MyClass. Это приведет к ошибке во время компиляции. Как пояснялось ранее, в любом классе, реализующем интерфейс, должны быть реализованы все методы, определенные в этом интерфейсе, в том числе и те, что наследуются из других интерфейсов. Сокрытие имен при наследовании интерфейсов
Когда один интерфейс наследует другой, то в производном интерфейсе может быть объявлен член, скрывающий член с аналогичным именем в базовом интерфейсе. Такое сокрытие имен происходит в том случае, если член в производном интерфей се объявляется таким же образом, как и в базовом интерфейсе. Но если не указать в объявлении члена производного интерфейса ключевое слово new, то компилятор вы даст соответствующее предупреждающее сообщение. Явные реализации