Смекни!
smekni.com

Основы алгоритмизации и программирования 2 (стр. 20 из 32)

5.1.Объектно-ориентированное программирование

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

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

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

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

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

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

5.2.Объект

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

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

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

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

Диаграммы, использованные в данной главе, создавались с помощью программы Microsoft Visio, которая поставляется с коммерческой версией VS.

На рисунке 6.1 приводится UML-представление класса, предназначенного для описания принтера, названного Printer. Имя класса изображено в верхней секции этого квадрата (к двум его нижним секциям мы обратимся немного позднее).

На рисунке 6.2 изображено UML-представление экземпляра класса Printer с именем myPrinter. Здесь в верхней секции располагается имя экземпляра, за ним следует имя соответствующего класса. Имена разделяются двоеточием.

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

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

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

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

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

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