Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Очень важно запомнить, что метод деструктора объекта не вызывается сразу, как только данный объект перестает использоваться.

Лекция 9. Объектно-ориентированное программирование.

Объектно-ориентированное программирование — это относительно новый подход к созданию компьютерных приложений, в котором предпринимается попытка решить многие проблемы, возникающие при применении "традиционного" программирования. Тип программирования, с которым вы были до сих пор знакомы, известен под названием функционального (или процедурного) программирования.

Он очень часто приводит к созданию так называемых монолитных приложений, в которых все функциональные возможности содержатся в небольшом числе модулей (зачастую в одном). Применяя методы ООП, мы очень часто будем использовать большое количество программных модулей, каждый из которых предоставляет только одну функциональную возможность, причем каждый модуль может существовать отдельно от остальных и даже быть совершенно независимым. Такой модульный метод написания программ оказывается более гибким и увеличивает возможности для повторного использования кода.

В качестве более наглядной иллюстрации ООП представим себе сложное приложение в виде высококлассного гоночного автомобиля. Если бы использовались традиционные способы программирования, то этот автомобиль представлял бы собой единое целое. И пожелай мы его усовершенствовать, нам бы пришлось заменить его целиком, отправив на завод-изготовитель для доводки заводскими специалистами (или купить новый). Если же применяются методы ООП, то можно просто приобрести новый двигатель и, следуя прилагающимся к нему инструкциям, заменить его самостоятельно. В "традиционном" приложении порядок выполнения прост и прямолинеен.

Приложения загружаются в память, их выполнение начинается в точке А и завершается в точке В, после чего они выгружаются из памяти. В процессе выполнения такого приложения могут использоваться самые разнообразные объекты, например, файлы на различных носителях или возможности, предоставляемые видеокартой, однако основное тело вычислений расположено в едином месте. Весь код, как правило, предназначается для манипуляций над данными с помощью различных математических и логических средств. Способы такого манипулирования обычно очень просты благодаря применению базовых типов (таких как целый и логический) дляболее сложного представления данных.

При использовании ООП такая прямолинейность встречается редко. И хотя результат достигается тот же самый, способ его получения зачастую оказывается совершенно отличным. Методы ООП в большей степени основываются на структуре и значении данных, а также на взаимодействии между различными данными. Это обычно требует больших усилий при разработке проекта, но дает преимущество расширяемости. После того как соглашение о способе представления конкретного типа данных достигнуто, оно может использоваться и в более поздних версиях приложения, и в совершенно новых приложениях. Тот факт, что такое соглашение уже существует, позволяет радикально сократить время, затрачиваемое на разработку. Это позволяет объяснить вышеприведенный пример с гоночным автомобилем. В этом случае в качестве соглашения применяется такая структура кода для "двигателя", которая позволяет использовать новый код (новый двигатель) взамен старого без всяких проблем и не требует отправки автомобиля на завод.

Кроме соглашений о представлении данных, ООП часто позволяет упростить жизнь за счет соглашений о структуре и об использовании более абстрактных сущностей. Например, соглашение может быть достигнуто не только относительно формата данных, который должен применяться при отправке выходного потока на какое-либо устройство вроде принтера, но и относительно способов обмена данными с этим устройством. Это будет касаться инструкций, которые оно может воспринимать и в дальнейшей работе.

Что такое объект

Объект — это строительный блок ООП-приложения. В этом блоке инкапсулируется некоторая часть приложения, которая может представлять собой процесс, группу данных или какую-либо более сложную сущность. В простейшем смысле объект очень напоминает тип структуры и в котором содержатся члены в виде переменных и функций различных типов. Совокупность переменных представляет данные, хранящиеся в этом объекте, а функции обеспечивают доступ к функциональным возможностям объекта. Несколько более сложные объекты могут вообще не содержать никаких данных; вместо это они могут представлять некоторый процесс и состоять исключительно из функций. Например, можно использовать объект, представляющий принтер, которой состоит из функций, обеспечивающих контроль за работой этого устройства (распечатать документ, распечатать тестовую страницу и т. д.).

Объекты в С# создаются на основе типов точно так же, как и переменные. Тип объекта известен в ООП под специальным названием "класс объекта". Мы можем использовать определения классов для создания экземпляров объектов, что означает создание реального поименованного экземпляра данного класса. Словосочетание "экземпляр данного класса" и термин "объект" в данном случае означают одно и то же, однако уверяем вас, что, вообще говоря, "класс" и "объект" обозначают фундаментально отличающиеся понятия.

Unified Modeling Language (UML — унифицированный язык моделирования). UML — это язык, разработанный для моделирования приложений с использованием тех объектов, из которых они строятся, тех операций, которые они выполняют, и тех вариантов их применения, для которых они предназначаются.

Свойства и поля

Свойства и поля обеспечивают доступ к данным, хранящимся в объекте. Данные, содержащиеся в объектах,— это то, что отличает один объект от другого, поскольку в различных объектах одного и того же класса могут храниться различные значения свойств и полей.

Теперь нам потребуется ввести еще один термин. Различные части информации, хранящиеся в объекте, в совокупности определяют состояние объекта.

Представьте себе класс объектов с именем CupOfCoffee (чашка кофе), описывающий чашку кофе. При создании экземпляра этого класса (т. е. при создании объекта данного класса) мы должны описать его состояние, для того чтобы объект был осмысленным. В этом случае мы могли бы использовать такие свойства и поля, которые позволят программе, использующей этот объект, задавать марку кофе, определять, добавлены ли в кофе сахар и молоко, является ли этот кофе растворимым и т. д. В таком случае объект, представляющий чашку кофе, будет обладать определенным состоянием, например, "колумбийский фильтрованный кофе с молоком и двумя кусочками сахара".

Как поля, так и свойства являются типизированными, поэтому информацию, содержащуюся в них, можно хранить в переменных типа string, int и т. п. Однако свойства отличаются от полей тем, что они не обеспечивают непосредственного доступа к данным. Объекты обладают возможностью изолировать пользователей, которым не требуется точное представление о структуре существующих свойств, от реального устройства своих данных. Если для описания числа кусочков сахара в экземпляре CupOfCoffee мы используем поле, то пользователи смогут занести в это поле любое значение, какое им заблагорассудится; если же мы используем свойство, то мы сможем ограничить это значение диапазоном от 0 до 2.

Вообще говоря, для организации доступа к состоянию лучше использовать свойства, а не поля, поскольку в этом случае мы обладаем большим контролем за происходящим, хотя синтаксис и в том, и в другом случае применяется один и тот же. Режим доступа к свойствам также может быть четко определен для данного объекта. Некоторые свойства могут использоваться в режиме "только чтение", что дает возможность просматривать их, но не изменять (по крайней мере, непосредственно). Очень часто полезными оказываются способы, позволяющие одновременно считывать несколько различных частей информации. Например, мы можем описать свойство класса СupОfСoffее с именем Description (описание), использующееся в режиме "только чтение", которое при обращении будет возвращать строку, описывающую состояние некоторого экземпляра данного класса (например, строку, приведенную выше). Эти же самые данные можно было бы получить, обращаясь к нескольким различным свойствам, однако использование одного свойства позволяет экономить время и усилия. Аналогичным образом можно использовать свойства, работающие в режиме "только запись".

Подобно тому как мы имеем возможность установить режим чтения/записи свойств, мы можем задать тип доступа совместно для полей и свойств. Это позволяет определять, какие программы имеют доступ к этим членам: доступны ли они для всего кода (public — общие), только для кода в рамках данного класса (private — частные), или же доступ к ним определяется по более сложной схеме (этот вопрос будет рассматриваться в настоящей главе по мере необходимости). Чрезвычайно распространенной является практика, когда поля описываются как частные, а доступ к ним организовывается посредством свойств, описанных как общие. Это означает, что код в рамках данного класса обладает непосредственным доступом к данным, хранящимся в поле, а общее свойство скрывает эти данные от внешних пользователей и не позволяет им записывать в эти данные недопустимые значения. Принято говорить, что общие члены предоставляются данным классом.

Для большей наглядности давайте отождествим это с областью действия переменной. Частные поля и свойства в таком случае можно представить как локальные по отношению к объекту, которому они принадлежат, в то время как область действия общих полей и свойств также распространяется и на код, внешний по отношению к данному объекту.

При представлении класса посредством UML вторая секция используется для изображения свойств и полей.

На рисунке 1 можно видеть представление нашего класса

cupofcoffee, в котором описано пять членов (неважно, свойств или полей — в UML между ними не существует никаких отличий), обсуждавшихся нами ранее. Каждое вхождение содержит следующую информацию:

• Тип доступа: символ 4- используется для общего члена,

символ - используется для частного члена.

• Имя члена.

• Тип члена.

В качестве разделителя между именем и типом члена используется двоеточие.

Методы

Метод — это термин, используемый для обозначения функций, предоставляемых данным объектом. Методы могут вызываться точно так же, как и любые другие функции, и в них так же, как и в функциях, могут использоваться возвращаемые значения и параметры.

Методы применяются для обеспечения доступа к функциональным возможностям объектов. Подобно полям и свойствам, они могут быть общими или частными, ограничивая по мере необходимости доступ к ним из внешнего кода. Методы часто учитывают состояние объекта при своей работе и обладают доступом к частным членам, например, к частным полям. Так, в классе CupOfCoffee мы можем описать метод с именем AddSugar() (добавить сахар), который обеспечит использование более удобного синтаксиса для увеличения значения свойства сладости кофе, чем присвоение соответствующего значения свойству sugar (сахар). В UML при описании объектов для изображения функций используется третья секция прямоугольника Используемый в этом случае синтаксис аналогичен применяемому для полей и свойств, за исключением того, что в конце строки указывается тип возвращаемого значения, а также приводятся параметры. В UML каждый параметр изображается с одним из следующих идентификаторов: in, out или inout. Эти идентификаторы используются для обозначения направления потока данных, при этом out и inout в первом приближении соответствуют применяемым в С# ключевым словам out и ref. Идентификатор in примерно соответствует такому поведению С#, когда отсутствуют оба ключевых слова.

Объектом может быть все

В С# и.NET Framework объектом может быть все, что угодно. Функция Main() в консольном приложении является методом класса. Все типы переменных, рассмотренных нами, являются классами. Каждая из использовавшихся команд представляет собой свойство или метод, Например, <Строка>. Length, <Строка>.ToUpper() и т. д. В данном случае точка отделяет имя экземпляра объекта от свойства или от имени метода.

Объекты существуют буквально повсеместно, и синтаксис, который требуется для их использования, зачастую оказывается очень простым. Действительно, он настолько прост, что до настоящего времени позволял нам сосредоточиться на более фундаментальных аспектах С#.

Жизненный цикл объекта

У каждого объекта имеется четко определенный жизненный цикл, который длится с момента использования определения класса до уничтожения объекта. Кроме обычного состояния "используется", в жизненном цикле объекта присутствуют еще два важных этапа:

Создание объекта — состояние, когда происходит первоначальное создание экземпляра объекта. Такая инициализация известна под названием создания объекта и осуществляется конструктором объекта.

• Уничтожение объекта — состояние, когда происходит уничтожение объекта, при котором очень часто возникает необходимость проведения различных восстановительных мероприятий, например освобождения памяти. Эта работа входит в функции деструктора объекта.

Конструкторы

Инициализация объекта происходит автоматически. Нам не приходится беспокоиться, допустим, о поиске свободной памяти, в которой будет размещен новый объект. Однако иногда возникают ситуации, когда на этапе инициализации может потребоваться выполнение каких-либо дополнительных действий. Например, очень часто бывает необходимо инициализировать данные, хранящиеся в объекте. Как раз это и входит в функции конструктора.

У каждого объекта имеется конструктор, используемый по умолчанию, который представляет собой метод без параметров. Его имя совпадает с именем самого класса. Определение класса может включать в себя несколько конструкторов. Они могут иметь отличающиеся сигнатуры, которые используются для создания экземпляра объекта. Для присваивания начальных значений данным, хранящимся внутри объекта, часто применяются конструкторы с параметрами.

В С# конструктор можно вызвать, введя ключевое слово new. Например, мы можем создать объект типа string следующим образом:

string myString = new string ();

Объекты также могут создаваться с помощью конструктора, используемого не по умолчанию. Как и имя конструктора по умолчанию, имена этих конструкторов совпадают с именем класса, но у них имеются еще и параметры. Используются они аналогичным образом:

string myString = new string{“a”, 10);

В результате применения этого конструктора будет создана новая строка, которой в качестве начального значения будет присвоено "аааааааааа", т. е. символ "а", повторенный десятикратно.

Конструкторы, подобно полям, свойствам и методам, могут быть общими или частными. Код, внешний по отношению к данному классу, не может использовать для создания экземпляра объекта частный конструктор; для этого необходимо воспользоваться общим конструктором. Таким способом мы можем, например, заставить пользователей нашего класса применять конструктор, использующийся не по умолчанию.

В некоторых классах вообще отсутствуют общедоступные конструкторы, что означает невозможность для внешнего кода создавать экземпляры данного класса. Однако, как вы вскоре сможете убедиться, такие классы вовсе не являются совершенно бесполезными.

Деструкторы

Деструкторы используются в.NET Framework для того, чтобы выполнять уборку за объектами. В общем случае нам не требуется писать какой бы то ни было код для метода деструктора; напротив, за нас будет работать операция, выполняющаяся по умолчанию. Однако если необходимо выполнить какие-либо важные действия перед уничтожением экземпляра объекта, то можно задать определенные инструкции.

Очень важно запомнить, что метод деструктора объекта не вызывается сразу, как только данный объект перестает использоваться.

Когда, например, мы выходим за область действия переменной, она становится недоступной для нашего кода, но при этом она может по-прежнему существовать где-нибудь в памяти компьютера. Только после того как сборщик мусора среды исполнения.NET выполнит свою работу, она будет окончательно уничтожена.

Это означает, что не следует полагаться на деструктор в плане освобождения ресурсов, которые использовались экземпляром объекта, поскольку объект может оставаться неиспользуемым на протяжении длительного времени. Если используемые ресурсы критичны, то это может привести к возникновению проблем.

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...