Г. Шилдт - С# 3.0 Полное руководство. 2010 (1160798), страница 71
Текст из файла (страница 71)
это означает, что в ней могут храниться ссылки на объект любого класса, реализующего интерфейс 1Яег1ея. В данном случае она служит для ссылки на объекты с щось и ргйщесь классов ВуТноя и Рг1щея аютветственно, в которых реализован интерфейс 1Яег1ея. И еще одно замечание: переменной ссылки на интерфейс доступны только методы, объявленные в ее интерфейсе. Поэтому интерфейсную ссылку нельзя использовать для доступа к любым другим переменным н методам, которые не поддерживаются объектом класса, реализующего данный интерфейс.
Интерфейсные свойства Аналогично методам, свойства указываются в интерфейсе вообще без тела. Ниже приведена общая форма объявления интерфейсного свойства. // Интерфейсное свойство тип иия( чест яест ) Очевидно, что в определении интерфейсных свойств, доступных только для чтения или только для записи, должен присутствовать единственный аксессор: ктег или яег соответственно. Несмотря на то что объявление свойства в интерфейсе очень похоже на объявление автоматически реализуемого свойства в классе, между ними все же имеется отличие.
При объявлении в интерфейсе свойство не становится автоматически реализуемым. В этом случае указывается только имя и тнп свойства, а его реализация предоставляется каждому реализующему классу Кроме того, при объявлении свойства в интерфейсе не разрешается указывать модификаторы доступа для аксессоров. Например, аксессор яет. не может быть указан в интерфейсе как ргйчаге. Ниже в качестве примера приведен переделанный вариант интерфейса 1Яег1ея и класса Вутноя, в котором свойство нехг используется для получения и установки следующего по порядку числа, которое больше предыдущего на два. // Использовать свойство я интерфейсе. пя1пд Яуягелы риьаас тпгегтясе 1зеггея ( // Интерфейсное свойство.
Рпс нехс ( Следукщее Следующее Следующее Следующее Следующее Следукщее Следующее Следуктиее Следукщее Следующее четное число равно 2 простое число равно 3 четное число равно 4 простое число равно 5 четное число равно б простое число равно 7 четное число равно 8 простое число равно 11 четное число равно 10 простое число равно 13 Глава (2. Интерфейсы, структуры и перечисления 369 370 Часть ). Язык С№ Пес) // возвратить следующее до порядку число яек; // установить следующее число ) // Реализовать интерфейс 13егтез. с1аяз ВуТноз: 18ег1ез ( 1пс ча12 рпЫТс ВуТноя () ча1 = Ок // Получить или установить значение. риЫТс Тпс Нехс ( Пег ( ча1 т= 2; гегпгп ча1; ) зег ( на1 = ча1це; ) ) ) // Продемонстрировать применение интерфейсного свойства. с1аяя БегтеяОещоз ( ягаг1с чо1о ма1п() ( ВуТноя оЬ = пен ВуТноз()к Сопзо1е.ыг1ге11пе["1пНачать с числа 21")к оЬ.Нехс = 21) Тог(тпг 1=0; 1 < 5; 1зт) Сопяо1е.ыгагевапе("Следующее число равно " т оЬ.Иехс); При выполнении этого кода получается следующий результат: Следующее число Следуцццее число Следующее число Следующее число Следующее число равно 2 равно 4 равно б равно 8 равно 10 Начать с числа 21 Следующее число равно 23 Следуцццее число равно 25 // Получить доступ к последовательному ряду чисел с помощью свойства Тот(кпс 1=0; 1 < 5; 1+з) Сопзо1е.ыгтсеьапе( "следующее число равно " + оь.нехг)) Глава (2.
Интерфейсы, структуры и перечисления 371 Следующее число равно 27 Следующее число равно 29 Следующее число равно 31 Интерфейсные индексаторы В интерфейсе можно также указывать индексаторы. Ниже приведена общая форма объявления интерфейсного индексатора. // Интерфейсный индексатор тип элемента гнфв(1пс импекс]( чею вест ) Как и прежде, в объявлении интерфейсных индексаторов, доступных только для чтения или только для записи, должен присутствовать единственный аксессор: Пес или зес соответственно. Ниже в качестве примера приведен еще один вариант реализации интерфейса 1Яеггев, в котором добавлен индексатор только для чтения, возвращающий тьй элемент числового ряда. // добавить индексатор а интерфейс.
пвгпч Яувлещт рпб11с 1плегласе тзег1ев ( // Интерфейсное свойство. 1пк нехк ( дегт // возвратить следующее по порядку число вект // установить следующее число // Интерфейсный индексатор. 1пс Гига (гпс гпбех] ( чегт // возвратить указанное в ряду число // Реализовать интерфейс тзеггев. с1авв ВУТнов: 1зег1ев ( 1пг уа17 рпп11с ВУТиов() ( ча1 = От ) // Получить или установить значение с помощью свойства. рпю11с 1пв Нехс ( чек ( та1 += 27 гевпгп ча1) 372 часть ). язык С» ) зес ( ча1 = ча1се; ! ) // получить значение по индексу. рпЬ11с фпе СЬ1з(фпп 1пс(ех! ( дес ( ча1 = 0; Гог(фпс 1=0) 1 < фпбех) 1ьт) ча1 += 2; гесигп ча1) ) ) ! // Продемонстрировать применение интерфейсного // индексатора.
с1азв Вег1езоещо4 ( зпае1с чо1с) Иа1п() ( Вутноз оЬ = пен Вутноз(); // Получить доступ к последовательному ряду чисел с помощью свойства. Гог(ьпп 1=0; 1 < 5; 1ьт) Сопзо1е.игфее01пе( "следующее число равно " + оь.мехе); Сопзо1е.иг1Се11пе("(пначать с числа 21")г оЬ.Мехе = 21) Гоп(фпп 1=0; 1 < 5; 1++) Сопзо1е.иг1Се11пе( "Следующее число равно " + оЬ.Мехе)4 Сопзо1е.нг1пе01пе("1пебросить в 0"); оЬ.Мехе = 04 Вот к какому результату приводит выполнение этого кода: равно 2 равно 4 равно б равно 8 равно 10 Следующее число Следующее число Следующее число Следующее число Следующее число Начать с числа 21 Следующее число равно 23 // Получить доступ к последовательному ряду чисел с помощью индексатора Гог(фпе 1=0) 1 < 5) 1ьт) Сопзо1е.игф<е11пе( "Следующее число равно " + оЬ(1))) Глава (2.
Интерфейсы, структуры и перечисления 373 Следующее число равно 25 Следующее число равно 27 Следуцццее число равно 29 Следующее число равно 31 Сбросить в О Следукщее число равно О Следующее число равно 2 Следующее число равно 4 Следуицее число равно б Следующее число равно 3 Наследование интерФейсов Один интерфейс может наследовать другой. Синтаксис наследования интерфейсов такой же, как и у классов. Когда в классе реализуется один интерфейс, наследуюпкнй другой, в нем должны быть реализованы все члены, определенные в цепочке наследования интерфейсов, как в приведенном ниже примере.
// Пример наследования интерфейсов. оэапд Яуэцелп роЫ1с 1пцегкасе гй ( чоаб МеСЫ ()т чо1б Мегп2()т ) // В базовый интерфейс включены методы Мецн1() и // Меци2(), а в производный интерфейс добавляется // еще один метод — меспЗ(). рпЫас апцегвасе 1В: гл ( чоки МеСПЗ()т ) // В этом классе должны быть реализованы все методы // интерфейсов 1А и 1В. с1авв МУС1авв: 1В ( роЫгс Уогб Мегн1() ( Сопэо1е.ыг1сеьгпе("Реализовать метод Мець1().")т ) рпЬ11с чоаб МеСП2() ( Сопэо1е.ыгфцеьапе("Реализовать метод МеСП2(].")т ) роо11с чоаб Мегьз() ( Сопэо1е .Нгаце11пе (" Реализовать метод Мегнз () . ") т ) ) с1авэ 1РЕхгепб ( 3(4 Часть!, язык Сз ясэятс тяте Мате() ( МуС1аяя ОЬ = ЬЕх МуС1аяя() оЬ.МеСЬ1()т оЬ.МеСЬ2()т ЬЬ.МеСЬЗ()т ) ) Ради интереса попробуйте удалить реализацию метода меТЫ () из класса муС1аяя.
Это приведет к ошибке во время компиляции. Как пояснялось ранее, в любом классе, реализующем интерфейс, должны быть реализованы все методьь определенные в этом интерфейсе, в том числе и те, что наследуются из других интерфейсов. Сокрытие имен при наследовании интерфейсов Когда один интерфейс наследует другой, то в производном интерфейсе может быть объявлеи член, скрывающий член с аналогичным именем в базовом интерфейсе. Такое сокрытие имен происходит в том случае, если член в производном интерфейсе объявляется таким же образом, как и в базовом интерфейсе. Но если ие указать в объявлении члена производного интерфейса ключевое слово пеы, то компилятор выдаст соответствующее предупреждающее сообщение.
Явные реализации При реализации члена интерфейса имеется возможность указать его имя полностлью вместе с именем самого интерфейса. В этом случае получается пенал реализация члена интерфейса, или просто явная реализация. Так, если объявлен интерфейс 1Мутт тькеггасе 1Мугт ( ъпс Мумекь(тпс х)т ) то следующая его реализация считается вполне допустимой: с1яяя МуС1эяя: тиутт ( пе 1иутГ.МуиеСЬ(вьк х) ( гееягь х / Зт ) Как видите, при реализации члена мумесь () интерфейса 1Му1т указывается его полное имя, включающее в себя имя его интерфейса. Для явной реализации интерфейсного метода могут быть две причины. Во-первых, когда интерфейсный метод реализуется с указаиием его полного имени, то такой метод оказывается доступным ие посредством объектов класса, реализующего данный иитерфейс, а по интерфейсной ссылке.
Следовательно, явная реализация позволяет реализовать интерфейсный метод таким образом, чтобы ои не стал открытым членом класса, предоставляющего его реализацию. И во-вторых, в одном классе могут быть реализованы два интерфейса с методами, объявленными с одинаковыми именами и сигиатурами. Но Глава )2. Интерфейсы, структуры и перечисления 375 неоднозначность в данном случае устраняется благодаря указанию в именах этих методов их соответствующих интерфейсов. Рассмотрим каждую из этих двух возможностей явной реализации на конкретных примерах. В приведенном ниже примере программы демонстрируется интерфейс 1ечеп, в котором объявляются два метода: Хзечеп () и Хаос(б () .
В первом из них определяется четность числа, а во втором — его нечетность. Интерфейс Хечеп затем реализуется в классе МуС1аяя. При этом метод 1яобб () реализуется явно. // Реализовать член интерфейса явно. паапа Зуясешт Хпсегтасе 1Ечеп ( Ьоо1 1яооб(апс х)т Ьоо1 ХяЕчеп(1пг х)т ) с 1 а я я МуС1а я в: 1 Ечеп ( // Явная реализация. Обратите внимание на то, что // этот член является закрытым по умолчанию. Ьоо1 1Ечеп.1яооб(апг х) ( Хт((хт2) != 0) гесцгп Ггце; е1яе гегцгп та1яет ) // Обычная реализация. рцЬ11с Ьоо1 1яЕчеп(апс х) ( 1Ечеп о = Сваял // Интерфейсная ссылка на вызывающий объект.