|
Программирование >> Программирование с использованием ajax
Для выполнения подобных задач в процессе инициализации предусмотрены статические конструкторы. У класса может быть только один статический конструктор, у которого не должно быть никаких модификаторов доступа и не может быть никаких параметров. Статический конструктор никогда не может вызываться напрямую; вместо этого он может вызываться в одном из следующих случаев: □ при создании экземпляра того класса, в котором содержится данный статический конструктор; □ при получении доступа к какому-то статическому члену класса, в котором содержится данный статический конструктор. В обоих этих случаях сначала вызывается статический конструктор и только потом создается экземпляр класса или получается доступ к статическим членам. Сколько бы экземпляров класса не создавалось, его статический конструктор будет вызываться только один раз. Чтобы отличать статические конструкторы от тех, что описывались ранее в этой главе, все нестатические конструкторы еще также называют конструкторами экземпляров. Статические классы Довольно часто может возникать желание использовать классы, имеющие только статические члены, которые не могут применяться для создания экземпляров объектов (вроде класса Console). Кратчайшим путем для этого, вместо преобразования всех конструкторов класса в приватные, является применение статического класса. Статический класс может содержать только статические члены и не может иметь конструкторов экземпляра, поскольку по своей природе не допускает создания экземпляров. Статические классы могут, однако, обладать статическим конструктором, как описывалось в предыдущем разделе. Тем, кто является полным новичком в ООП, не помешает передохнуть перед изучением остального материала этой главы. Очень важно полностью разобраться со всеми базовыми понятиями и только затем приступать к рассмотрению более сложных аспектов. Приемы объектно-ориентированного программирования Теперь, когда изучены основы и известно, что собой представляют объекты и как они работают, пришла пора перейти к рассмотрению других функциональных возможностей объектов. В настоящем разделе речь пойдет о следующем: □ интерфейсы; а наследование; □ полиморфизм; □ отношения между объектами; а перегрузка операций; а события; а ссылочные типы и типы-значения. Интерфейсы Интерфейс (interface) - это коллекция общедоступных методов и свойств, которые объединяются вместе для инкапсуляции конкретной функциональности. После определения интерфейса его можно реализовать в классе. Это означает, что в таком случае класс будет поддерживать все свойства и члены, специфицируемые данным интерфейсом. Важно обратить внимание на то, что интерфейсы не могут существовать сами по себе. Создавать экземпляр интерфейса, как это можно делать с классом, нельзя. Помимо этого, интерфейсы не могут содержать никакого кода, реализующего их члены, они могут лишь определять их, а реализоваться те должны непосредственно в классах, которые реализуют данный интерфейс. В приведенном ранее примере класса CupOfCoffee многие из свойств и методов более общего назначения, вроде AddSugar (), Milk, Sugar и Instant, можно было бы сгруппировать вместе в интерфейс, назвать его, скажем, IHotDrink (Горячий напиток) (имена интерфейсов обычно сопровождаются префиксом в виде заглавной буквы I), и применять для других объектов, например, объектов класса CupOf Tea (Чашка чая). Это позволило бы работать со всеми этими объектами похожим образом и при этом все равно разрешить им иметь свои собственные свойства (например, объектам CupOfCoffee - свойство ВеапТуре (Сорт кофейных зерен), а объектам CupOf Tea - свойство Leaf Туре (Сорт чайных листьев)). Интерфейсы, реализуемые для объектов, в UML изображаются с использованием синтаксиса в форме окружности с линией. На рис. 8.6 члены интерфейса IHotDrink вынесены в отдельный прямоугольник и перечислены с использованием подобного классам синтаксиса. lnterface IHotDrink -hinstant: bool -hMilk : bool -hSugar: byte -i-Description : string -bAddSugar(in amount: byte) : byte CupOfCoffee -ьВеапТуре : string -Q IHotDrink CupOfTea -HLeafType : string -Q) IHotDrink Puc. 8.6. Представление интерфейсов в UML Один класс может поддерживать несколько интерфейсов, а несколько классов могут поддерживать один и тот же интерфейс. Следовательно, интерфейсы позволяют упрощать жизнь для пользователей и других разработчиков. Например, предположим, что есть некий код, в котором используется объект с определенным интерфейсом. Если не использовать другие свойства и методы этого объекта, один объект можно будет легко заменять другим (приводившийся ранее код, в котором использовался интерфейс IHotDrink, например, мог работать как с экземплярами CupOfCoffee, так и с экземплярами CupOfTea). Кроме того, сам разработчик данного объекта может выпустить его обновленную версию, и при условии, что она поддерживает находящийся в В качестве альтернативного варианта, экземпляр объекта <имя переменной> можно также создавать и в виде части оператора using: using ( <имя класса> <имя переменной> = new <имя класса>{)) И в том, и в другом случае переменная <имя переменной> будет использоваться внутри блока using и автоматически удаляться в его конце (т.е. по завершении выполнения содержащегося внутри этого блока кода будет автоматически вызываться метод Dispose О ). Наследование Наследование (inheritance) является одним из самых важных механизмов в ООП. Любой класс может наследоваться от другого класса, а это значит, что он будет иметь все те же члены, что и класс, от которого он унаследован. В терминологии ООП класс. эксплуатации интерфейс, другой разработчик сможет легко применить новую версию в своем коде. После публикации интерфейса, т.е. предоставления к нему доступа другим разработчикам или конечным пользователям, рекомендуется не изменять его. Можно представить, что интерфейс является своего рода контрактом между создателями класса и его потребителями, в котором создатели, по сути, заявляют, что каждый класс, поддерживающий интерфейс X, будет поддерживать такие-то методы и свойства. Если интерфейс позже изменится, например, в результате модернизации лежащего в основе кода, это может привести к тому, что его потребители больше не смогут работать с ним корректным образом или вообще утратят возможность запускать его. Поэтому вместо этого рекомендуется создавать новый интерфейс, расширяющий возможности старого и имеющий, например, такой номер версии, как Х2. Такой подход уже стал стандартным, поэтому интерфейсы с пронумерованными версиями встречаются довольно часто. Освобождаемые объекты Одним из заслуживающих особого внимания интерфейсов является интерфейс IDisposable. Объект, поддерживающий этот интерфейс, должен обязательно реализовать метод Dispose (), т.е. предоставлять код этого метода. Dispose () может вызываться тогда, когда объект уже больше не нужен (например, непосредственно перед его выходом за пределы области видимости), и должен использоваться для освобождения любых критических ресурсов, которые в противном случае могут оставаться занятыми до тех пор, пока не будет вызван метод деструктора во время сборки мусора. Это обеспечивает больший контроль над ресурсами, которыми пользуются объекты. Язык С# позволяет применять структуру, делающую применение этого метода очень эффективным. Ключевое слово using дает возможность инициализировать использующий критические ресурсы объект в таком блоке кода, где метод Dispose () вызывается при достижении конца автоматически: <имя класса> <имя переменной> = new <имя класса> {) ; using {<имя переменной>)
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |