ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание
Шрифт:
Массивы интерфейсных типов
Следует понимать, что один и тот же интерфейс может реализовываться многими типами, даже если эти типы не находятся в рамках одной иерархии классов. В результате можно получать очень мощные программные конструкции, Предположим, например, что мы построили одну иерархию классов для описания кухонной посуды, а другую – для описания садового инвентаря.
Эти иерархии абсолютно не связаны между собой с точки зрения классического наследования, но с ними можно обращаться полиморфно, используя программирование на основе интерфейсов. Для иллюстрации
Замечание. С учетом общеязыковой природы .NET важно подчеркнуть, что можно определить интерфейс на одном языке (C#), а реализовать его на другом (VB .NET). Но чтобы выяснить, как это сделать, нам потребуется понимание структуры компоновочных блоков .NET, что является темой обсуждения главы 11.
Явная реализация интерфейса
В определении IDraw3D мы были вынуждены назвать наш единственный метод Draw3D, чтобы избежать конфликта с абстрактным методом Draw, определенным в базовом классе Shape. Такое определение интерфейса вполне допустимо, но более естественным именем для метода было бы Draw.
Если вносить такое изменение, то потребуется также обновить нашу реализацию DrawIn3D.
Теперь предположим, что мы определили новый класс Line (линия), который получается из абстрактного класса Shape и реализует iDraw3D (оба из них теперь определяют одинаково названные абстрактные методы Draw).
Класс Line компилируется беспрепятственно. Рассмотрим следующую логику Main.
С
Теперь рассмотрим родственную проблему. Что делать, если вам нужно гарантировать, что методы, определенные данным интерфейсом, будут доступны только с помощью интерфейсных ссылок, а не объектных? В настоящий момент члены, определенные интерфейсом IPointy, доступны как с помощью объектных ссылок, так и по ссылке на IPointy.
Ответ на оба вопроса дает явная реализация интерфейса. Используя этот подход, вы можете гарантировать, что пользователь объекта сможет получить доступ К методам, определенным данным интерфейсом, только с помощью правильной интерфейсной ссылки, не допуская при этом конфликта имен. Для примера рассмотрите следующий обновленный класс Line (предполагая, что вы соответствующим образом обновили Hexagon и Circle).
Как видите, при явной реализации члена интерфейса общий шаблон выглядит так: возвращаемоеЗначение ИмяИнтерфейса.ИмяМетода(аргументы). Здесь есть несколько "подводных камней", о которых следует знать. Прежде всего, не допускается определять явно реализуемые члены с модификаторами доступа. Например, следующий синтаксис недопустим.
Главной причиной использования явной реализации метода интерфейса является необходимость "привязки" соответствующего метода интерфейса к уровню интерфейса. Если добавить ключевое слово public, то это будет означать, что данный метод является членом открытого сектора класса, и "привязка" будет отменена. Тогда вызывающая сторона сможет вызывать только метод Draw, определенный базовым классом Shape на объектном уровне.