Полное руководство. С# 4.0 - Шилдт Герберт
Шрифт:
Интервал:
Закладка:
Вот к какому результату приводит выполнение этой программы:Следующее четное число равно 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Следующее число равно 4Следующее число равно 6Следующее число равно 8Следующее число равно 10Начать с числа 21Следующее число равно 23Следующее число равно 25Следующее число равно 27Следующее число равно 29Следующее число равно 31Интерфейсные индексаторы
В интерфейсе можно также указывать индексаторы. Ниже приведена общая формаобъявления интерфейсного индексатора.// Интерфейсный индексатортип_элемента 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, то компилятор выдаст соответствующее предупреждающее сообщение.Явные реализации
При реализации члена интерфейса имеется возможность указать его имя полностью вместе с именем самого интерфейса. В этом случае получается явная реализациячлена интерфейса, или просто явная реализация. Так, если объявлен интерфейс IMyIFinterface IMyIF { int MyMeth(int x);}
то следующая его реализация считается вполне допустимой:class MyClass : IMyIF { int IMyIF.MyMeth(int x) { return x / 3; }}
Как видите, при реализации члена MyMeth() интерфейса IMyIF указывается егополное имя, включающее в себя имя его интерфейса.