Развитие
объектно-ориентированного метода обусловлено ограниченностью других методов
программирования, разработанных ранее. Чтобы лучше понять и оценить значение
ООП, необходимо разобраться, в чем состоит эта ограниченность и каким образом
она проявляется в традиционных языках программирования.
С. Pascal,
FORTRAN и другие сходные с ними языки программирования относятся к категории
процедурных языков. Каждый оператор такого языка является указанием компьютеру
совершить некоторое действие, например принять данные ог пользователя,
произвести с ними определенные действия и вывести результат этих действий на
экран. Программы, написанные на процедурных языках, представляют собой
последовательности инструкций.
Для небольших
программ не требуется дополнительной внутренней организации (часто называемой
термином парадигма). Программист создает перечень инструкций, а компьютер выполняет
действия, соответствующие этим инструкциям.
Деление на функции
Когда размер
программы велик, список команд становится слишком громоздким. Очень небольшое
число программистов способно удерживать в голове более 500 строк программного
кода, если этот код не разделен на более мелкие логические части. Функция
является средством, облегчающим восприятие при чтении текста программы (термин
функция употребляется в языках С и C++; в других языках программирования это же
понятие называют подпрограммой или процедурой). Программа, построенная на
основе процедурного метода, разделена на функции, каждая из которых в идеальном
случае выполняет некоторую законченную последовательность действий и имеет явно
выраженные связи с другими функциями программы. Можно развить идею разбиения
программы на функции, объединив несколько функций в модуль (зачастую модуль
представляет собой отдельный файл). При этом сохраняется процедурный принцип:
программа делится на несколько компонентов, каждый из которых представляет
собой набор инструкций. Деление программы на функции и модули является основой
структурного программирования. Структурное программирование представляет собой
нечто не вполне определенное, однако в течение нескольких десятков лет, пока не
была разработана концепция объектно-ориентированного программирования, оно
оставалось важным способом организации программ.
Объектно-ориентированный подход
Основополагающей
идеей объектно-ориентированного подхода является объединение данных и действий,
производимых над этими данными, в единое целое, которое называется объектом.
Функции объекта, называемые в C++ методами или функциями-членами, обычно предназначены
для доступа к данным объекта. Если необходимо считать какие-либо данные объекта,
нужно вызвать соответствующий метод, который выполнит считывание и возвратит
требуемое значение. Прямой доступ к данным невозможен. Данные сокрыты от
внешнего воздействия, что защищает их от случайного изменения. Говорят, что
данные и методы инкапсулированы.
Термины
сокрытие и инкапсуляция данных являются ключевыми в описании
объектно-ориентированных языков. Если необходимо изменить данные объекта, то,
очевидно, это действие также будет возложено на методы объекта. Никакие другие
функции не могут изменять данные класса. Такой подход облегчает написание,
отладку ииспользование программы.
Характеристики объектно-ориентированных
языков
Здесь мы
рассмотрим несколько основных элементов, входящих в состав
объектно-ориентированных языков, в частности в состав языка C++:
Объекты
Когда вы
подходите к решению задачи с помощью объектно-ориентированного метода, то
вместо проблемы разбиения задачи на функции вы сталкиваетесь с проблемой
разбиения ее на объекты. Мышление в терминах объектов оказывается гораздо более
простым и наглядным, чем в терминах функций, поскольку программные объекты
схожи с объектами реального мира.
Что должно
представляться в программе в виде объектов? Окончательный ответ на этот вопрос
может дать только ваше воображение, однако приведемнесколько советов, которые могут оказаться
полезными:
♦ Физические
объекты.
·Автомобили при моделировании уличного движения.
·Схемные элементы при моделировании цепи
электрического тока.
·Страны при создании экономической модели.
·Самолеты при моделировании диспетчерской системы.
♦ Элементы
интерфейса.
·Окна.
·Меню.
·Графические объекты (линии, прямоугольники,
круги).
·Мышь, клавиатура, дисковые устройства, принтеры.
♦ Структуры
данных.
·Массивы.
·Стеки.
·Классы
Когда мы
говорим об объектах, мы говорим, что они являются экземплярами классов. Что это
означает? Рассмотрим следующую аналогию. Практически все компьютерные языки
имеют стандартные типы данных; например, в C++ есть целый тип int. Мы можем
определять переменные таких типов в наших программах:
int day:
int count;
int divisor:
int answer:
Наследование
Понятие класса
приводит нас к понятию наследования. В повседневной жизни мы часто сталкиваемся
с разбиением классов на подклассы: например, класс животные можно разбить на
подклассы млекопитающие, земноводные, насекомые, птицы и т. д. Класс наземный
транспорт делится на классы автомобили, грузовики, автобусы, мотоциклы и т. д.
Принцип,
положенный в основу такого деления, заключается в том, что каждый подкласс
обладает свойствами, присущими тому классу, из которого выделен данный
подкласс. Автомобили, грузовики, автобусы и мотоциклы обладают колесами и
мотором, являющимися характеристиками наземного транспорта. Кроме тех свойств,
которые являются общими у данных класса и подкласса, подкласс может обладать и
собственными свойствами: например, автобусы имеют большое число посадочных мест
для пассажиров, в то время как грузовики обладают значительным пространством и
мощностью для перевозкитяжеловесных
грузов и т. д.
Подобно этому,
в программировании класс также может породить множество подклассов. В C++
класс, который порождает все остальные классы, называется базовым классом;
остальные классы наследуют его свойства, одновременно обладая собственными свойствами.
Такие классы называются производными.
Повторное использование кода
Разработанный
класс может быть использован в других программах. Это свойство называется
возможностью повторного использования кода. Аналогичным свойством в процедурном
программировании обладают библиотеки функций, которые можно включать в
различные программные проекты.
В ООП
концепция наследования открывает новые возможности повторного использования
кода. Программист может взять существующий класс, и, ничего не изменяя, добавить
в него свои элементы. Все производные классыунаследуют эти изменения, и в то же время каждый из производных классов
можномодифицировать отдельно.
Пользовательские типы данных
Одним из
достоинств объектов является то, что они дают пользователю возможность создавать
свои собственные типы данных. Представьте себе, что вам необходимо работать с
объектами, имеющими две координаты, например х и у. Вам хотелось бы совершать
обычные арифметические операции над такими объектами, например:
positionl = position2 + origin
где переменные positionl, position2 и origin
представляют собой наборы из двух координат. Описав класс, включающий в себя
пару координат, и объявив объекты этого класса с именами positionl, position2 и
origin, мы фактически создадим новый тип данных. В C++ имеются средства,
облегчающие создание подобных пользовательских типов данных.
Полиморфизм и перегрузка
Обратите
внимание на то, что операции присваивания = и сложения + для типа position
должны выполнять действия, отличающиеся от тех, которые они выполняют для
объектов стандартных типов, например int. Объекты positionl и прочие не
являются стандартными, поскольку определены пользователем как принадлежащие
классу position. Как же операторы = и + распознают, какие действия необходимо
совершить над операндами? Ответ на этот вопрос заключается в том, что мы сами
можем задать эти действия, сделав нужные операторы методами класса position.
Использование
операций и функций различным образом в зависимости от того, с какими типами
величин они работают, называется полиморфизмом. Когда существующая операция, например
= или +, наделяется возможностью совершать действия над операндами нового типа,
говорят, что такая операция является перегруженной. Перегрузка представляет
собой частный случай.
Универсальный язык моделирования (UML)
UML можно
условно называть графическим языком, предназначенным для моделирования
компьютерных программ. Под моделированием понимается создание наглядной
визуальной интерпретации чего-либо. UML позволяет создавать подобную интерпретацию
программ высокоуровневой организации.
Родоначальниками
UML стали три независимых языка моделирования, создателями которых были
соответственно Гради Буч, Джеймс Рэмбо и Ивар Джекобсон. В конце 90-х годов они
объединили свои разработки, в результате чего получили продукт под названием
универсальный язык моделирования (UML),который был одобрен OMG — консорциумом компаний, определяющих
промышленные стандарты.
Почему UML
необходим? Во-первых, потому, что бывает трудно установить взаимоотношение
частей большой программы между собой посредством анализа ее кода. Как мы уже
видели, объектно-ориентированное программирование является более прогрессивным,
чем процедурное. Но даже при этом подходе для того, чтобы разобраться в
действиях программы, необходимо как минимум представлять себе содержание ее
кода. полиморфизма и является важным инструментом ООП.
Наиболее
важным средством UML является набор различных видов диаграмм. Диаграммы классов
иллюстрируют отношения между различными классами, диаграммы объектов — между
отдельными объектами, диаграммы связей отражают связь объектов во времени и т.
д. Все эти диаграммы, по сути, отражают взгляды на программу и ее действия с
различных точек зрения.
Тем не менее
не стоит рассматривать UML как средство разработки программного обеспечения.
UML является лишь средством для иллюстрирования разрабатываемого проекта. Несмотря
на возможность применения к любому типу языков, UML наиболее полезен в
объектно-ориентированном программировании. Как мы уже упомянули во введении, мы
будем постепенно рассматривать.