Г. Шилдт - С# 3.0 Полное руководство. 2010 (1160798), страница 72
Текст из файла (страница 72)
геспгп !о.Хаоса(х); ) с1аяя Оешо ( ясасас чотб Маап() ( МуС1аяя оЬ = пен МуС1аяя()т Ьоо1 геяц1Г) геяц1г = оЬ.1яЕчеп(4)т 11(геви1Г) Сопяо1е.нгасеъйпе("4 — четное число.") // геяц1С = оЬ.1яобб(4)) // Ошибка, член Хяобб // интерфейса 1Ечеп не является открытым.
// Но следующий код написан верно, поскольку в нем // сначала создается интерфейсная ссылка типа 1Ечеп // на объект класса МуС1аяз, а затем по этой ссылке // вызывается метод 1яобб(). ХЕчеп Хает = (1Ечеп) оЬт геяц1С = лает.1яобб(3)т ХЕ(геяц1С) Сопяо1е.ыг1геътпе("3 — нечетное число.")! 376 Часть ). Язык ь№ В приведенном выше примере метод 1яос(б () реализуется явно, а значит, он недоступен как открытый член класса муС1аяя. Напротив, он доступен только по интерфейсной ссылке. Именно поэтому он вызывается посредством переменной о ссылочного типа 1Ечеп в реализации метода 1яЕчеп () . Ниже приведен пример программы, в которой резлизуются два интерфейса, причем в обоих интерфейсах объявляется метод месь () .
Благодаря явной реализации исключается неоднозначность, характерная для подобной ситуации. // Воспольяоваться явной реализацией для // устранения неоднозначности. цвапо Зуясекп 1пгегтасе 1МУ1Г А ( апс месь(гпс х)т 1пгеггасе 1МУ1Г В ( гпг Месь(1пг х); ) // Оба интерфейса реализуются в классе МуС1аяя. сгаяя Муогаяя: 1МУ1Г А, 1МУ1Г В ( // Реализовать оба метода Мегп() явно. апС 1МУ1Г А.мегл(гпг х) ( гегцгп х + хт ) 1пг 1МУ1Г В.Месь(апг х) гегцгп х * хт ) // Вызывать метод месь() по интерфейсной ссылке. рцв11с Спг МеСЬА(гпг х)( 1му1Г А а оЬт а оЬ = СЬгят гегцгп а оЬ.Месь(х); // вызов интерфейсного метода 1му1Г А ) рцв11с 1пг МеСЬВ(гпг х)( 1МУ1Г В Ь оЬт Ь оЬ = СЬггят геСцгп Ь оЬ.меСЬ(х)т // вызов интерфейсного метода 1МУ1Г В ) ) с1аяя ГО1гиаюея ( ягаС1с того Магп() ( МуС1авя оЬ = пен МуС1аяя() Сопяо1е.иггге("Вызов метода 1му1Г А.меСЬ(): ")т Сопяо1е.иг1се11пе(оЬ.МеСЬА(3))т Глава 12. Интерфейсы, структуры и перечисления 377 Сопзо1е.ик1се("Вызов метода тму1Г В.меть(): ")т Сопзо1е.игткешпе(оп.метнВ(3))т ) ) Вот к какому результату приводит выполнение этой программы: Вызов метода 1му1Г А.меби(): б Вызов метода тмутГ В.иетн(): Э Анализируя приведенный выше пример программы, прежде всего обратите внимание на одинаковую сигнатуру метода Мег)т () в обоих интерфейсах, 1МуП' А и 1Мутг В.
Когда оба этих интерфейса реализуются в классе Му С 1 вез, для каждого из них в отдельности это делается явно, те. с указанием полного имени метода мвтп () . А поскольку явно реализованный метод может вызываться только по интерфейсной ссылке, то в классе муС1в аз создаются две такие ссылки: одна — для интерфейса 1мутг А, другая — для интерфейса 1му1В В. именно по этим ссылкам происходит обрицение к объектам данного класса с целью вызвать методы соответствующих интерфейсов, благодаря чему и устраняется неоднозначность. Выбор между интерфейсом и абстрактным классом Одна из самых больших трудностей программирования на С(т состоит в правильном выборе между интерфейсом и абстрактным классом в тех случаях, когда требуется описать функциональные возможности, но не реализацию. В подобных случаях рекомендуется придерживаться следующего общего правила: если какое-то понятие можно описать с точки зрения функционально~о назначения, не уточняя конкретные детали реализации, то следует использовать интерфейс.
А если требуются некоторые детали реализации, то данное понятие следует представить абстрактным классом. Стандартные интерфейсы для среды . НЕТ Ггамеиог1с Для среды .)ч)ЕТ Ргашешог11 определено немало стандартных интерфейсов, которыми можно пользоваться в программах на С(). Так, в интерфейсе Вузгем. 1Сомрвгв)з1е определен метод солтрагето (), применяемый для сравнения объектов, когда требуется соблюдать отношение порядка. Стандартные интерфейсы являются также важной частью классов коллекций, предоставляющих различные средства, в том числе стеки и очереди, для хранения целых групп объектов. Так, в интерфейсе яувсекп. Со11есе1опз. 1Со11естйоп определяются функции для всей коллекции, а в интерфейсе яузсем.
со11ессйопз. 1хпплтегагог — способ последовательного обращения к элементам коллекции. Эти и многие другие интерфейсы подробнее рассматриваются в части 11 данной книги. Структуры Как вам должно быть уже известно, классы относятся к ссылочным типам данных. Это означает, что объекты конкретного класса доступны по ссылке, в отличие от значений простых типов, доступных непосредственно.
Но иногда прямой доступ к объектам 378 Часть ). Язык С№ касс к значениям простых типов оказывается полезно иметь, лапример, ради повышения эффективности программы. Ведь каждый доступ к объектам (даже самым мелким) по ссылке связан с дополнительными издержками иа расходование вычислительных ресурсов и оперативной памяти. Для разрешения подобных затруднений в С№ предусмотрена структура, которая подобна классу, ио относится к типу значения, а ие к ссылочиому типу данных. Структуры объявляются с помощью ключевого слова зсгисг и с точки зрения сиитаксиса подобны классам.
Ниже приведена общая форма объявления структуры. вггисг имя: интерфейсы ( // объявления членов где имя обозиачает конкретное имя структуры. Одни структуры пе могут наследовать другие структуры и классы или служить в качестве базовых для других структур и классов. (Разумеется, структуры, как и все остальные типы данных в С№, наследуют класс оЬ) есс.) Тем ие менее в структуре можно реализовать один или более интерфейс, которые указываются после имени структуры списком через запятую. Как и у классов, у каждой структуры имеются свои члены: методы, поля, ипдексаторы, свойства, операторные методы и события.
В структурах допускается также определять конструкторы, ио ие деструкторы. В то же время для структуры нельзя определить конструктор, используемый по умолчанию (т.е. конструктор без параметров). Дело в том, что конструктор, вызываемый по умолчанию, определяется для всех структур автоматически и ие подлежит изменению.
Такой конструктор инициализирует поля структуры значениями, задаваемыми по умолчанию. А поскольку структуры не поддерживают наследование, то их члены иельзя указывать как аЬвггасе, ч№ггда1 или ргоеесее((. Объект структуры может быть создан с помбщью оператора пем таким же образом, как и объект класса, ио в этом иет особой необходимости. Ведь когда используется оператор пем, то вызывается конструктор, используемый по умолчанию. А когда этот оператор не используется, объект по-прежнему создается, хотя и ие инициализируется.
В этом случае инициализацию любых членов структуры придется выполнить вручную. В приведенном ниже примере программы демонстрируется применение структуры для хранения информации о книге. // ПродемонСтрировать применение структуры. ивапд Бувсем; // Определить структуру. вггисг Воок ( риЫ№с вгг№пд аигьог> риЫ№с вгггпд т№Ые> риЫ№с Ьпг Соругъдьг~ риЫЬс Воок(вггъпд а, всгглд Г, Ьпс с) аисьог = в; т№Ые = ъч соругьдье = с> ) Глава!2. Интерфейсы, структуры и перечисления 3(9 // Продемонстрировать применение структуры Воол.
с1аяя Эсгцссоешо ( якак1с чо1б Налп() ( Воол Ьоол1 пен Воол("Герберт Шилдт", "Полный справочник по СЮ 3.0", 2009)т // вызов явно заданного конструктора Воол Ьоол2 = пен Воол()т // вызов конструктора по умолчанию Воок ЬооКЗт // конструктор не вызывается Сопяо1е.ыглкеълпе(Ьоолг.ацспог ь ", ьоок1.т1г1е + ", (с) " + ьоок1.соруггчьг)т Сопяо1е .Иглкеълпе () т ТГ(Ьоол2.ТТГ1е == пц11) Сопяо1е.нгьсеьгпе('"Член Ьоол2.ТТГ1е пуст."); // Л теперь ввести информацию в структуру Ьоолз. Ьоо)т2.ТТГ1е "О дивный новый мир"; ьоолз.ацспог = "Олдос Хаксли"; Ьоок2.СоруглдЬГ 1932( Сопяо1е. Игксе ( "Структура Ьоол2 теперь содержит: чп")т Сопяо1е.Иггсеълпе(Ьоол2.ацкьог + ", " + Ьоол2.ТТГ1е ь ", (с) " ь Ьоол2.Соруг19ЬГ) Сопяо1е.нгъсеъъпе()т // Сопяо1е.Иггкеълпе(ЬоокЗ.тлс1е)т // неверно, этот // член структуры нужно сначала инициализировать ЬоокЗ.ТТГ1е = "Красный шторм"; Сопяо1е.иг1кеъгпе(ЬооКЗ.Т1г1е)т // теперь верно ) ) При выполнении этой программы получается следующий результат: Герберт Вилле, Полный справочник по СУ 3.0, (с) 2009 Член Ьоол2.Т1Г1е пуст.
Структура Ьоол2 теперь содержит: Олдос Хаксли, О дивный новый мир, (с) 1932 Красный шторм Как демонстрирует приведенный выше пример программы, структура может быть инициализирована с помощью оператора пен для вызова конструктора или же путем простого объявления объекта. Так, если используется оператор пеы, то поля структуры инициализируются конструктором, вызываемым по умолчанию (в этом случае во всех полях устанавливается задаваемое по умолчанию значение), или же конструктором, определяемым пользователем.