- •Предисловие
- •Введение Эволюция разработки программного обеспечения
- •Технологии программирования
- •Основные понятия объектно-ориентированного программирования
- •Инкапсуляция
- •Свойства
- •Векторные свойства
- •Создание и уничтожение объектов
- •Конструкторы
- •Деструкторы
- •Наследование
- •Свойства
- •Конструкторы и деструкторы класса-предка
- •Полиморфизм, виртуальные и динамические методы
- •Статическое перекрытие виртуальных методов
- •Виртуальное перекрытие конструкторов и деструкторов
- •Абстрактные методы
- •Области видимости
- •Перекрытие и переопределение свойств
- •Перекрытие методов доступа к свойствам
- •Приведение объектных типов, операторы as и is
- •Агрегация
- •События
- •Процедурный тип
- •Создание события
- •Инициаторы события
- •Делегирование
- •Внутреннее устройство объекта
- •Указатели на класс
- •Виртуальные конструкторы
- •Методы класса
- •Обработка исключительных ситуаций
- •Операторы try...Except и try...Finally
- •Исключительные ситуации как объекты
- •Перегрузка методов
- •Перегрузка виртуальных методов
- •Параметры по умолчанию
- •Основы объектно-ориентированного анализа и проектирования
- •Объектно-ориентированная модель
- •Классы и объекты
- •Заключение Применение объектно-ориентированного программирования
- •Библиографический список
Классы и объекты
Природа объектов и классов уже рассматривалась в разделе «Введение в объектно-ориентированное программирование». Вернемся к ней еще раз, с тем, чтобы обобщить все сказанное.
Неформально объект может быть определен как осязаемая реальность, проявляющая четко выделяемое поведение. С точки зрения восприятия человеком объектом может быть:
-
осязаемый или видимый предмет,
-
нечто, воспринимаемое мышлением,
-
нечто, на что направлена мысль или действие.
Таким образом, объект в человеческом восприятии – это модель части окружающей действительности и именно в таком смысле термин объект был впервые введен в программировании. Но объекты в программировании – это не только объекты реального мира. Это могут быть, например, процессы или виртуальные машины.
Объект – нечто, обладающее состоянием, поведением и идентичностью; структура и поведение схожих объектов определяет общий для них класс; термины «экземпляр класса» и «объект» взаимозаменяемы.
Во многих ситуациях поведение объекта определяется его историей – важна последовательность совершаемых над объектом действий. Такая зависимость поведения от предшествующих событий объясняется тем, что у объекта есть внутреннее состояние.
Состояние объекта характеризуется перечнем (обычно статическим) всех свойств данного объекта и текущими (обычно динамическими) значениями каждого из этих свойств.
Перечень свойств объекта составляет неизменяемую основу объекта. Но в ряде случаев состав свойств объекта может изменяться. Пример – самообучающиеся системы.
Все свойства имеют некоторые значения – простые количественные характеристики или ссылки на другой объект. Причем другие объекты в свою очередь имеют свое внутренне состояние и могут его изменять.
Объекты не существуют изолированно, а подвергаются воздействию извне, или сами воздействуют на другие объекты.
Поведение – это то, как объект действует и реагирует; поведение выражается в терминах изменения состояния объекта и передачи сообщений.
Для описания процесса взаимодействия объектов применительно к разным языкам программирования используются разные термины: передача сообщений, вызов методов или функций-членов. Поведение объекта с одной стороны определяется воздействием на него со стороны других объектов. С другой стороны оно определяется текущим состоянием самого объекта. В результате поведения объекта его состояние может меняться.
Поведение объекта может быть выражено через операции.
Операция – это услуга, которую класс может предоставить своим клиентам. Наиболее распространенные операции:
-
модификатор – изменяет состояние объекта,
-
селектор – считывает состояние объекта, но не изменяет его,
-
итератор – позволяет организовать доступ ко всем частям объекта в строго определенной последовательности,
-
конструктор – создание объекта и/или его инициализация,
-
деструктор – освобождает состояние объекта и/или разрушает сам объект.
Чаще всего операции – это методы. Но возможно использование и свободных подпрограмм, которые также называют утилитами класса.. Рекомендуется использовать только методы, но возможны ситуации – например, если операция выполняется сразу над несколькими объектами разных классов – когда удержаться от искушения организовать операцию как свободную подпрограмму сложно.
Совокупность всех методов и свободных процедур, относящихся к конкретному объекту, образует протокол этого объекта. Протокол определяет поведение объекта. В сложных абстракциях полезно подразделять протокол на частные аспекты поведения, которые называют ролями. Роль – это маска, которую носит объект, она определяет контракт абстракции с ее клиентами. Например, компьютер можно рассматривать как машину для обработки информации с соответствующими характеристиками, как товар, имеющий цену или как груз при перевозке по железной дороге.
Наличие внутреннего состояния, от которого зависит поведение, приводит к тому, что объект может быть формально описан как конечный автомат.
Идентичность – это такое свойство объекта, которое отличает его от всех других объектов.
Не следует путать адресуемость и идентичность, что происходит при программировании, когда объекты именуют. Также не следует путать идентичность и значение данных, что характерно для баз данных, где объекты различают по ключевому атрибуту.
В ООП идентичность объекта может определяться теми физическими адресами в памяти компьютера, в которых располагаются поля данного объекта. Именно физические адреса, а не имя переменной-указателя. Потому что в разные моменты работы программы указатель может ссылаться на разные объекты.
Также возможно, что два разных указателя в результате выполнения операции присваивания будут ссылаться на один и тот же объект – такую ситуацию называют структурной зависимостью. Структурная зависимость порождает в ООП много проблем: утечку памяти, неправильный доступ к памяти, непрогнозируемые изменения состояний и т.п.
Отношения между объектами: сами по себе объекты не представляют никакого интереса – система реализуется в процессе их взаимодействия. Любая программа в рамках объектно-ориентированного подхода представляет собой «сообщество хорошо воспитанных объектов, которые вежливо просят друг друга об услугах». Причем свойства и поведение системы в целом определяется не столько свойствами и поведением каждого отдельного компонента, сколько их взаимодействием. Например, самолет, по определению – совокупность элементов, каждый из которых по своей природе стремиться упасть на землю, но за счет совместных непрерывных усилий преодолевающих эту тенденцию.
Для ООП интерес представляют два типа отношений между объектами:
-
связи,
-
агрегация.
Связи определяются как физическое или концептуальное соединение между объектами. Объект сотрудничает с другими объектами через связи, соединяющие его с ними.
Объект, который запрашивает услугу, называют клиентом. Объект, который услугу предоставляют, называют сервером. В этих терминах связь может быть определена следующим образом: Связь – это соотношение, через которое клиент запрашивает услугу у объекта-сервера или через которое один объект находит путь к другому. Обычно связь осуществляется через вызов метода.
Связь между объектами и передача сообщений обычно односторонняя, хотя технически она может быть и взаимной. Но, хотя передаваемое сообщение инициируется клиентом, данные передаются в обоих направлениях – данные и результат.
Объект может выполнять одну из следующих трех ролей:
-
Деятель – может воздействовать на другие объекты, но сам никогда не подвергается воздействию;
-
Сервер – может только подвергаться воздействию;
-
Агент – может выступать как в активной, так и в пассивной роли.
С проблемой установки связи между объектами связана проблема видимости.
Пусть есть два объекта А и В. Чтобы послать сообщение из А в В нужно, чтобы В был в каком-то смысле видим для А. На стадии анализа об этом можно не заботиться, но на стадии реализации видимость объектов должна быть обеспечена.
Существуют следующие способы обеспечить видимость:
-
сервер глобален по отношению к клиенту,
-
сервер (или указатель на него) передан клиенту в качестве параметра операции,
-
сервер является частью клиента,
-
сервер локально порождается клиентом в ходе выполнения какой-либо операции.
Агрегация. В то время как связи описывают равноправные отношения между объектами типа клиент-сервер, агрегация описывает отношение целого и части, приводящие к соответствующей иерархии объектов, причем, идя от целого (агрегата), можно придти к его частям (атрибутам).
Агрегация может означать физическое вхождение одного объекта в другой, но не обязательно. Например: самолет состоит из крыльев, акционер владеет акциями.
Выбирая одно из двух – связь или агрегацию – надо иметь в виду следующее. Агрегация предпочтительнее, когда следует скрыть части в целом. Иногда связи предпочтительнее, поскольку они слабее и менее ограничительны.
Объект, являющийся атрибутом другого объекта (агрегата), имеет связь со своим агрегатом. Через эту связь агрегат может посылать ему сообщения.
Класс – это некое множество объектов, имеющих общую структуру и общее поведение.
Объект означает конкретную сущность, определенную во времени и пространстве, класс определяет лишь абстракцию существенного объекте. Любой конкретный объект является экземпляром класса. Таким образом, для того, чтобы использовать в программе объект, нужно разработать класс, которому он принадлежит.
Лежащая в основе ООП идея инкапсуляции требует разграничения внешнего облика, то есть интерфейса, и внутреннего устройства – то есть реализации. Реализация класса никому, кроме него самого, не интересна. Главное в интерфейсе – объявление операций, поддерживаемых экземплярами класса.
Интерфейс класса может быть разделен на три части:
-
открытую – видимую всем клиентам;
-
защищенную – видимую самому классу, его подклассам и друзьям;
-
закрытую – видимую только самому классу и его друзьям.
Разные языки программирования предусматривают разные комбинации этих частей.
Отношения между классами: имеются следующие виды отношений:
-
ассоциация,
-
наследование,
-
агрегация,
-
использование,
-
инстацирование,
-
метакласс.
Наиболее общим из них является ассоциация. Обычно в процессе проектирования ассоциация уточняется и превращается в какую-либо иную связь.
Ассоциация означает, что есть какая-то связь, не уточняя ее характер. Ассоциация должна работать в обе стороны. Например, торговая точка: две абстракции – товары и продажи. Они связаны. Задавшись товаром, можно выйти на сделку когда он был продан и наоборот.
Реализация отношения типа ассоциация, означает, что классы должны содержать ссылки друг на друга.
Наследование – это такое отношение между классами, когда один класс повторяет структуру и поведение другого класса (одиночное наследование) или других классов (множественное наследование).
Наследование используется, если у объектов есть что-то общее или между ними есть смысловая ассоциация.
Наследование можно рассматривать как способ управления повторным использованием программ, то есть как простое решение разработчика о заимствовании полезного кода.
Наследование обычно предполагает наличие полиморфизма.
Агрегация. Отношение агрегации между классами имеет непосредственное отношение к агрегации между их экземплярами. Агрегация бывает по значению и по ссылке. При включении по ссылке важно обеспечить создание и уничтожение включаемых объектов.
Скрытую агрегацию можно применять в языках с одиночным наследованием, чтобы обеспечить подобие множественного наследования.
Для того чтобы понять, наследование или агрегация имеет место, следует задаться вопросом – имеет место отношение «быть чем-то» или «являться частью чего-то». В первом случае это – наследование, во втором – агрегация.
Использование. Отношение использования между классами соответствует аналогичной связи между их объектами – отношения клиент-сервер.
Инстацирование. При инстацировании разрабатывается обобщенный класс, который еще называют параметризованным. Он представляет собой что-то вроде шаблона для построения других классов. Пример – шаблоны классов в С++. Шаблон может быть параметризован другими классами, объектами или операциями. Т.е. какие-то части описания и реализации класса, которые могут отличаться, заменены обозначениями. Далее эти обозначения – параметры можно заменить на конкретные имена типов, процедур и т.д. с помощью например команд препроцессора. Естественно, что параметризованный класс не является синтаксически правильным.
Если класс порожден от параметризованного класса, то говорят что между ними отношение инстацирования.
Наследование вообще более мощный механизм и через наследование можно получить большинство преимуществ обобщенных классов, но не наоборот.
Метаклассы. Любой объект является экземпляром какого-либо класса. Что будет, если обращаться с классами как с объектами? Получится класс класса – метакласс. Пример – указатели на класс в Object Pascal. Также к возможностям метаклассов относится поддержка статических элементов класса в С++.