Г. Шилдт - С#4.0 Полное руководство (1160795), страница 73
Текст из файла (страница 73)
// Воспользоваться явной реализацией для устранения неоднозначности. цяьпд Зуяьев; 390 Часть!. Язык С() ьпсегтасе тмуту А ( ьпС МеСЬ(1пС х); ) 1псегтасе 1му1Г В ( ьпс МеСЬ(1пС х)г Оба интерфейса реализуются а классе МуС1аяя. с1 я Мус1аяя : 1Мугр А, 1Муту В ( // Реализовать оба метода МеСЬ() явно. ьпС тмугр А.месь(ьпс х) ( геспгп х + х; ) ьпС 1Мугр В.МеСЛ(апС х) ( геспгп х * х; ) // Вызывать метод МеСЬ() по интерфейсной ссылке. рпььас 1ЬС МеСЬА(1пС х)( 1му1В А а оЬ; а оЬ = СЛ1ят гесогп а оЬ.МеСЛ(х)т // вызов интерфейсного метода 1му1Г А ) рпЬ11с ьпС МеСЬВ(1пС х)( 1Муту В Ь оЬГ Ь оЬ = Сьья; геСпгп Ь оЬ.МеСЬ(х)," // вызов интерфейсного метода 1му1Р В ) ) с1аяя ГО1ГНамея ( ясасьс то1с) Ма1п() ( МуС1аяя оЬ = пен МуС1аяя() Сопяо1е.нг1Се("Вызов метода 1му1Р А.меСЛ(): Сопяо1е.нгьсевьпе(оЬ.МеСЬА(3)); Сопяо1е.иггсе("Вызов метода 1му1Е В.месь(): "); Сопяо1е.игьсе11пе(оЬ.МеСЬВ(3)); ) Вот к какому результату приводит выполнение этой программы.
Вызов метода 1му1Г А.месь(): б Вызов метода 1му1Р В.меСЛ(): 9 Анализируя приведенный выше пример программы, обратим прежде всего внимание на одинаковую сигнатуру метода месь () в обоих интерфейсах, 1мутр А и 1Му1Р В. Когда оба этих интерфейса реализуются в классе Мус1аяя, для каждого из них в отдельности это делается явно, т.е. с указанием полного имени метода МеСЬ () . А поскольку явно реализованный метод может вызываться только по интерфейсной Глава 12. Интерфейсы, структуры н перечисления 391 ссылке, то в классе МуС1аяя создаются две такие ссылки: одна — для интерфейса 1Ыу1г А, а другая — для интерфейса 1))у1К Н. Именно по этим ссылкам происходит обращение к объектам данного класса с целью вызвать методы соответствующих интерфейсов, благодаря чему и устраняется неоднозначность. Выбор между интерфейсом и абстрактным классом Одна из самых больших трудностей программирования на С№ состоит в правильном выборе между интерфейсом и абстрактным классом в тех случаях, когда требуется описать функциональные возможности, но не реализацию.
В подобных случаях рекомендуется придерживаться следующего общего правила: если какое-то понятие можно описать с точки зрения функционального назначения, не уточняя конкретные детали реализации, то следует использовать интерфейс. А если требуются некоторые детали реализации, то данное понятие следует представить абстрактным классом. Стандартные интерфейсы для среды.НЕТ Гта№петтогк Для среды .НЕТ Ргатетчогк определено немало стандартных интерфейсов, которыми можно пользоваться в программах на С№.
Так, в интерфейсе Буясев. 1Соырага)з1е определен метод Сотрагето (), применяемый для сравнения объектов, когда требуется соблюдать отношение порядка. Стандартные интерфейсы являются также важной частью классов коллекций, предоставляющих различные средства, в том числе стеки и очереди, для хранения целых групп объектов. Так, в интерфейсе яуягеп. Со11есб1опя. 1Со11есг№оп определяются функции для всей коллекции, а в интерфейсе яуясеы.
Со11есг№опя . 1кпитегагог — способ последовательного обращения к элементам коллекции. Эти и многие другие интерфейсы подробнее рассматриваются в части П данной книги. Структуры Как вам должно быть уже известно, классы относятся к ссылочным типам данных. Это означает, что объекты конкретного класса доступны по ссылке, в отличие от значений простых типов, доступных непосредственно. Но иногда прямой доступ к объектам как к значениям простых типов оказывается полезно иметь, например, ради повышения эффективности программы.
Ведь каждый доступ к объектам (даже самым мелким) по ссылке связан с дополнительными издержками на расход вычислительных ресурсов и оперативной памяти. Для разрешения подобных затруднений в С№ предусмотрена структура, которая подобна классу, но относится к типу значения, а не к ссылочному типу данных. Структуры объявляются с помощью ключевого слова я с гнсс и с точки зрения синтаксиса подобны классам. Ниже приведена общая форма объявления структуры: всгнсг имя : инеереейоы ( объявления членов ) где имя обозначает конкретное имя структуры. 392 Часть ).
Язык С(г Одни структуры не могут наследовать другие структуры и классы или служить в качестве базовых для других структур и классов. (Разумеется, структуры, как и все остальные типы данных в С(), наследуют класс оЬП е с с) Тем не менее в структуре можно реализовать один или несколько интерфейсов, которые указываются после имени структуры списком через запятую. Как и у классов, у каждой структуры имеются свои члены: методы, поля, индексаторы, свойства, операторные методы и событил.
В структурах допускается также определять конструкторы, но не деструкторы. В то же время для структуры нельзя определить конструктор, используемый по умолчанию (т.е. конструктор без параметров). Дело в том, что конструктор, вызываемый по умолчанию, определяется для всех структур автоматически и не подлежит изменению. Такой конструктор инициализирует поля структуры значениями, задаваемыми по умолчанию.
А поскольку структуры не поддерживают наследование, то их члены нельзя указывать как аЬяггасг, чгггпа1 или ргогесгес(. Объект структуры может быть создан с помощью оператора пеы таким же образом, как и объект класса, но в этом нет особой необходимости. Ведь когда используется оператор пеи, то вызывается конструктор, используемый по умолчанию. А когда этот оператор не используется, объект по-прежнему создается, хотя и не инициализируется. В этом случае инициализацию любых членов структуры придется выполнить вручную. В приведенном ниже примере программы демонстрируется применение структуры для хранения информации о книге.
Продемонстрировать применение структуры. пя1пс Зуясега) 22 Определить структуру. ясгпсс Воок ( рсЬ1гс ясггпч Апплог) риЫгс ясггпч тгс1е) рпЫгс 1пг Соруггдлг) рпЬ1гс Воок(ясг1пд а, ясггпэ Г, гпс с) ( Апслог = а) тгсге = г; Соруггэлс = с) ) ) Продемонстрировать применение структуры ВооК. с1аяя Всгпсгбеюо ( ягаггс чогб Ма1п() ( Воок ЬооК1 = пен ВооК("Герберт Шилдт", "Полный справочник Ьо С() 4.0", 2010); // вызов явно заданного конструктора Воок Ьоок2 = пен ВооК(); // вызов конструктора по умолчанию ВооК Ьоокз( /! конструктор не вызывается Сопяо1е,иггсевьпе(Ьоок1.Аислог + ьооК1.тгг1е + ", (с) " + ьоок1.соруг1чьг)) Сопяо1е.иг1севдпе () ) 11(ЬооК2.тгс1е == пп11) Глава 12.
Интерфейсы, структуры и перечисления 393 Сопяо1е.нг1сеььпе("Член Ьоок2.Т1С1е пуст.") й теперь ввести информацию в структуру Ьоох2. Ьоок2.Т111е = "О дивный новый мир"( Ьоок2.кцспог = "Олдос Хаксли"; Ьоок2.СоруггдЬГ = 1932; Сопяо1е.нгьге("Структура Ьоок2 теперь содержит:Хп")( Сопяо1е.нггсеъгпе(Ьоок2.Лцсьог + Ьоок2.ТТГ1е + ", (с) " + Ьоок2.СоругьдЬС) Сопва1е.нггсеьепе(); Сопяо1е.нг1геььпе(ЪооХЗ.Т1С1е); /! неверно, этот член структуры !/ нужно сначала инициализировать ЬооХЗ.ТТГ1е = "Красный шторм"; сопяо1е.иг1геьгпе(ьоохЗ.тгг1е)( // теперь верно ) ) При выполнении этой программы получается следующий результат.
Герберт В)илдт, Полный справочник по С() 4.0, (с) 2010 Член Ьоок2.Т1С1е пуст. Структура Ьоох2 теперь содержит: Олдос Хаксли, О дивный новый мир, (с) 1932 Красный шторм Как демонстрирует приведенный выше пример программы, структура может быть инициализирована с помощью оператора пем для вызова конструктора или же путем простого объявления объекта. Так, если используется оператор пеи, то поля структуры инициализируются конструктором, вызываемым по умолчанию (в этом случае во всех полях устанавливается задаваемое по умолчанию значение), или же конструктором, определяемым пользователем. А если оператор пеи не используется, как это имеет место для структуры ЬООХЗ, то объект структуры не инициализируется, а его поля должны быть установлены вручную перед тем, как пользоваться данным объектом.
Когда одна структура присваивается другой, создается копия ее объекта. В этом заключается одно из главных отличий структуры от класса. Как пояснялось ранее в этой книге, когда ссылка на один класс присваивается ссылке на другой класс, в итоге ссылка в левой части оператора присваивания указывает на тот же самый объект, что и ссылка в правой его части.
А когда переменная одной структуры присваивается переменной другой структуры, создается копия объекта структуры из правой части оператора присваивания. Рассмотрим в качестве примера следующую программу. Скопировать структуру. цяьпд 5уягеш( // Опрелелить структуру. яггцсг Музггцсс ( РцЬ11с гпе хг ) 394 Часть (, Язык С() // Продемонстрировать приснаияание структуры. с1аяя ЗггнсСАяя1спзепя ( яяаьус тога Маап() ( Муяггнсг а! Муаягссг Ь! а.х = 10! Ь.х = 20! Сопяо1е.ыгзяеь]пе("а.х (0), Ь.х (1)", а.х, Ь.х); а = Ь! Ь.х = ЗО! сопяо1е.нг1сеъгпе("а.х (0], Ь.х (1]", а.х, Ь.х)! ) ) Вот к какому результату приводит выполнение втой программы. а.х 10, Ь.х 20 а.х 20, Ь.х 30 Как показывает приведенный выше результат, после присваивания а = Ь! переменные структуры а и Ь по-прежнему остаются совершенно обособленными, т.е.
переменная а не указывает на переменную Ь и никак не связана с ней, помимо того, что она содержит копию значения переменной Ь. Ситуация была бы совсем иной, если бы переменные а и Ь были ссылочного типа, указывая на объекты определенного класса. В качестве примера ниже приведен вариант предыдущей программы, где демонстрируется присваивание переменных ссылки на объекты определенного класса. // Использовать ссылки на объекты определенного класса. няьпч Буясеы! // Создать класс. с1аяя МуС1аяя ( ровьас апс х; ) // Показать присваияание разных объектов данного класса.
с1аяя С1аяяАяяудпзепп яяаяас тозе Мауп() МуС1аяя а = лен МуС1аяя()! МуС1аяя Ь = пен МуС1аяя()! а.х = 10; Ь.х = 20! Сопяо1е.игатеъапе("а.х (О), Ь.х (1)", а.х, Ь.х); а = Ь! Ь.х = ЗО! Глава 12. Интерфейсы, структуры и перечисления 395 сопяо1е.иг1се1гпе("а.х (0), Ь.х (1)", а.х, Ь.х)1 Выполнение этой программы приводит к следующему результату. .х Ш, Ь.х гО а.х 30, Ь.х ЗО Как видите, после того как переменная Ь будет присвоена переменной а, обе переменные станут указывать на один и тот же объект, т.е. на тот объект, на который первоначально указывала переменная Ь. О назначении структур В связи с изложенным выше возникает резонный вопрос зачем в С№ включена структура, если она обладает более скромными возможностями, чем класс? Ответ на этот вопрос заключается в повышении эффективности и производительности программ.