"Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning." Rich Cook ООП
Объектно-ориентированное программирование (ООП) ООП - основная методология программирования. Это стиль программирования, который фиксирует поведение реального мира таким способом, при котором детали его реализации скрыты. Истоки ОО - Симула-67, хотя первая полная реализация была в Smalltalk-80.Smalltalk-80 ООП стало популярным во второй половине 80-х в языках: С++, Objective C, Object Pascal, CLOS (ОО-расширение Lisp'a), Eiffel, Ada (в последних версиях), Java, С#.
ООП – решение кризиса ООП является последним звеном в длиной цепи решений, которые были предложены для разрешения "кризиса программного обеспечения". Кризис ПО означает, что те задачи, которые мы хотим решить, опережают наши возможности.
Сложные системы реального мира Персональный компьютер Дерево Человек Предприятие Государство
Признаки сложных систем Являются иерархическими и состоят из взаимозависимых подсистем, которые в свою очередь также могут быть разделены на подсистемы и т.д. – до самого низкого уровня. Выбор элементарных компонентов произволен и зависит от исследователя. Каждая часть системы имеет свою функцию и может рассматриваться независимо от других. Системы состоят из немногих типов подсистем, по-разному скомбинированных и организованных. Система сложнее, чем совокупность ее частей.
Алан Кей – фундаментальные характеристики ООП [Кау 1993]: Все является объектом Объект как хранит информацию, так и способен ее преобразовывать. Любой элемент решаемой задачи (дом, собака, услуга, химическая реакция, город, космический корабль и т. д.) может представлять собой объект. Объект можно представить как швейцарский нож: он является набором различных ножей и «открывашек» (хранение), но в то же самое время им мы можем резать или открывать что- либо (преобразование).
Программа совокупность объектов, указывающих друг другу что делать Для обращения к одному объекту другой объект «посылает ему сообщение». Возможно и «ответное сообщение». Программу можно представить себе как совокупность, например, 3-х объектов: писателя, ручки и листа бумаги. Писатель «посылает сообщение» ручке, которая в свою очередь «посылает сообщение» листу бумаги в результате мы видим текст (сообщение от листа к писателю).
Каждый объект имеет свою собственную «память», состоящую из других объектов Таким образом программист может скрыть сложность программы за довольно простыми объектами. Например, дом (сложный объект) состоит из дверей, комнат, окон, проводки и отопления. Дверь в свою очередь может состоять из собственно двери, ручки, замка и петель. Проводка также состоит из проводов, розеток, щитка.
У каждого объекта есть тип (класс) Класс (тип) определяет какие сообщения объекты могут посылать друг другу. Например, аккумуляторная батарея может передавать электролампе ток, а вот физическое усилие - нет. Каждый объект является представителем класса, который выражает общие свойства объектов (таких, как целые числа или списки).
В классе задается поведение (функциональность) объекта Тем самым все объекты, которые являются экземплярами одного класса, могут выполнять одни и те же действия. Все объекты одного типа могут получать одинаковые сообщения Например, есть 2 объекта: синяя и красная кружки. Обе разные по форме и материалу. Но из обеих мы можем пить (или не пить, если они пустые). В данном случае кружка это тип объекта.
Классы организованы в единую древовидную структуру с общим корнем, называемую иерархией наследования Память и поведение, связанное с экземплярами определенного класса, автоматически доступны любому классу, расположенному ниже в иерархическом дереве.
1 ый принцип ОО подхода - способ задания действий. Действие в ООП инициируется посредством передачи сообщений агенту (объекту), ответственному за действия. Сообщение содержит запрос на осуществление действия и сопровождается дополнительной информацией (аргументами), необходимой для его выполнения. Получатель - это агент, посылается сообщение. Если он принимает сообщение, то на него автоматически возлагается ответственность за выполнение указанного действия. В качестве реакции на сообщение получатель запустит некоторый метод, чтобы удовлетворить принятый запрос.
2 ой принцип ООП: Все объекты являются представителями (экземплярами) классов. Метод активизируемый объектом в ответ на сообщение, определяется классом, к которому принадлежит получатель сообщения. Все объекты одного класса используют одни и те же методы в ответ на одинаковые сообщения. Весь мир - это объекты, которые передают друг другу сообщения
3 ий принцип - знание о более общей категории разрешается использовать для более узкой категории - наследование. Классы могут быть организованы в иерархическую структуру с наследованием свойств. Дочерний класс (подкласс) наследует атрибуты родительского класса (надкласса), расположенного выше в иерархическом дереве.
Определение ООП ООП - совокупность принципов разработки программ, понятий и элементов языка, позволяющих успешно создавать программы большого объема. ООП базируется на связи в единое целое свойств и поведения предмета или процесса. Свойства предмета - это данные, которые его характеризуют. Поведение задается функциями.
Преимущества ООП Преимущества (при создании больших программ): использование при программировании понятий, более близких к предметной области; локализация свойств и поведения объекта о одном месте, позволяющая лучше структурировать и отлаживать программу; возможность создания библиотеки объектов и создания программы из готовых частей; исключение избыточного кода - можно многократно не описывать повторяющиеся действия; простая возможность внесения изменений в программу без изменения уже написанных частей, а в ряде случаев и без их перекомпиляции.
Недостатки ООП Недостатки ООП: снижение быстродействия программы, связанное с использованием виртуальных методов; идеи ООП не просты для понимания и в особенности для практического использования; для эффективного использования существующих ОО систем требуется большой объем первоначальных знаний.
Свойства ООП Инкапсуляция - скрытие деталей реализации; объединение данных и действий над ними. Наследование позволяет создавать иерархию объектов, в которой объекты-потомки наследуют все свойства своих предков. Свойства при наследовании повторно не описываются. Кроме унаследованных, потомок обладает собственными свойствами. Объект в C++ может иметь сколько угодно потомков и предков. Полиморфизм - возможность определения единого по имени действия, применимого ко всем объектам иерархии, причем каждый объект реализует это действие собственным способом. Класс (объект) – инкпасулированная абстракция с четким протоколом доступа
Принципы ОО представления программных систем Рассмотрение любой сложной системы требует применения техники декомпозиции разбиения на составляющие элементы. 2 схемы декомпозиции: алгоритмическая и ОО декомпозиция. В основе алгоритмической декомпозиции - разбиение по действиям - алгоритмам. ОО декомпозиция - разбиение по автономным лицам - объектам реального (или виртуального) мира. Эти лица (объекты) - более «крупные» элементы, каждый из них несет в себе и описания действий, и описания данных.
ОО представление ПС основывается на принципах абстрагирования, инкапсуляции, модульности и иерархической организации. Каждый из принципов не нов, но их совместное применение рассчитано на проведение ОО декомпозиции. Это определяет модификацию их содержания и механизмов взаимодействия друг с другом.
Абстрагирование Аппарат абстракции удобный инструмент для борьбы со сложностью реальных систем. Создавая понятие в интересах какой-либо задачи, мы отвлекаемся (абстрагируемся) от несущественных характеристик конкретных объектов, определяя только существенные характеристики. Например, в абстракции «часы» мы выделяем характеристику «показывать время», отвлекаясь от таких характеристик конкретных часов, как форма, цвет, материал, цена, изготовитель.
Абстрагирование сводится к формированию абстракций. Каждая абстракция фиксирует основные характеристики объекта, которые отличают его от других видов объектов. Абстракция концентрирует внимание на внешнем представлении объекта, позволяет отделить основное в поведении объекта от его реализации. Абстракцию удобно строить путем выделения обязанностей объекта. Пример: физический объект - датчик скорости, устанавливаемый на борту летательного аппарата (ЛА). Создадим его абстракцию: сформулируем обязанности датчика: знать проекцию скорости ЛА в заданном направлении; показывать текущую скорость; подвергаться настройке.
Инкапсуляция Инкапсуляция и абстракция - взаимодополняющие понятия: абстракция выделяет внешнее поведение объекта, а инкапсуляция содержит и скрывает реализацию, которая обеспечивает это поведение. Инкапсуляция достигается с помощью информационной закрытости. Обычно скрываются структура объектов и реализация их методов. Инкапсуляция является процессом разделения элементов абстракции на секции с различной видимостью. Инкапсуляция служит для отделения интерфейса абстракции от ее реализации. Пример: физический объект регулятор скорости. Обязанности регулятора: включаться; выключаться; увеличивать скорость; уменьшать скорость; отображать свое состояние.
Модульность В языках C++, Object Pascal, Ada 95 абстракции классов и объектов формируют логическую структуру системы. При производстве физической структуры эти абстракции помещаются в модули. В больших системах, где классов сотни, модули помогают управлять сложностью. Модули служат физическими контейнерами, в которых объявляются классы и объекты логической разработки. Модульность определяет способность системы подвергаться декомпозиции на ряд сильно связанных и слабо сцепленных модулей.
Общая цель декомпозиции на модули: уменьшение сроков разработки и стоимости ПС за счет выделения модулей, которые проектируются и изменяются независимо. Каждая модульная структура должна быть достаточно простой, чтобы быть полностью понятой. Изменение реализации модулей должно проводиться без знания реализации других модулей и без влияния на их поведение. Определение классов и объектов выполняется в ходе логической разработки, а определение модулей - в ходе физической разработки системы. Эти действия сильно взаимосвязаны, осуществляются итеративно.
Иерархическая организация Три механизма для борьбы со сложностью: абстракция (упрощает представление физического объекта); инкапсуляция (закрывает детали внутреннего представления абстракций); модульность (дает путь группировки логически связанных абстракций). Дополнение - иерархическая организация - формирование из абстракций иерархической структуры. Упрощаются понимание проблем заказчика и их реализация - сложная система становится обозримой человеком.
Задает размещение абстракций на различных уровнях описания системы. 2 инструмента иерархической организации в ОО системах: структура из классов («is a»-иерархия); структура из объектов («part of»-иерархия). «is а» - иерархическая структура строится с помощью наследования. Наследование определяет отношение между классами, где класс разделяет структуру или поведение, определенные в одном другом (единичное наследование) или в нескольких других (множественное наследование) классах.
«part of» - иерархическая структура базируется на отношении агрегации. Агрегация не является понятием, уникальным для ОО систем: любой ЯП, разрешающий структуры типа «запись», поддерживает агрегацию. Агрегация полезна в сочетании с наследованием: - агрегация обеспечивает физическую группировку логически связанной структуры; - наследование позволяет легко и многократно использовать эти общие группы в других абстракциях.
Сравнение элементов иерархий наследования и агрегации с точки зрения уровня сложности: при наследовании нижний элемент иерархии (подкласс) имеет больший уровень сложности (большие возможности); при агрегации - наоборот (агрегат обладает большими возможностями, чем его элементы).
Объекты В предметной области выделяются объекты – некоторые целостные сущности, обладающие определенным поведением. Объект Состояние (атрибуты)Поведение (методы) Интер фейс
Объекты Объект - конкретное представление абстракции. Объект обладает индивидуальностью, состоянием и поведением. Структура и поведение подобных объектов определены в их общем классе. Термины «экземпляр класса» и «объект» взаимозаменяемы.
Индивидуальность - это характеристика объекта, которая отличает его от всех других объектов. Состояние объекта характеризуется перечнем всех свойств объекта и текущими значениями каждого из этих свойств Стул Стоимость Вес Размеры Положение Цвет Перечень Свойств Купить() Продать() Взвесить() Переместить() Покрасить() Перечень операций
Объекты не существуют изолированно друг от друга. Они подвергаются воздействию или сами воздействуют на другие объекты. Поведение характеризует то, как объект воздействует на другие объекты (или подвергается воздействию) в терминах изменений его состояния и передачи сообщений. Поведение объекта является функцией как его состояния, так и выполняемых им операций (Купить, Продать, Взвесить, Переместить, Покрасить). Говорят, что состояние объекта представляет суммарный результат его поведения.
Операция обозначает обслуживание, которое объект предлагает своим клиентам. 5 видов операций клиента над объектом: 1) модификатор (изменяет состояние объекта); 2) селектор (дает доступ к состоянию, но не изменяет его); 3) итератор (доступ к содержанию объекта по частям, в строго определенном порядке); 4) конструктор (создает объект и инициализирует его состояние); 5) деструктор (разрушает объект и освобождает занимаемую им память).
Примеры операций: Вид операции Пример операции Модификатор Пополнеть (кг) Селектор Какой Вес (): integer Итератор Показать Ассортимент Товаров (): string Конструктор Создать Робот (параметры) Деструктор Уничтожить Робот ()
В чистых ОО ЯП операции могут объявляться только как методы - элементы классов, экземплярами которых являются объекты. Гибридные языки (C++, Ada 95) позволяют писать операции как свободные подпрограммы (вне классов). В общем случае все методы и свободные подпрограммы, ассоциированные с конкретным объектом, образуют его протокол. Протокол определяет оболочку допустимого поведения объекта и поэтому заключает в себе цельное (статическое и динамическое) представление объекта.
Большой протокол разделяют на логические группировки поведения. Эти группировки, разделяющие пространство поведения объекта, обозначают роли, которые может играть объект. Принцип выделения ролей:
С точки зрения внешней среды важное значение имеет понятие - обязанности объекта. Обязанности означают обязательства объекта обеспечить определенное поведение. Обязанностями объекта являются все виды обслуживания, которые он предлагает клиентам. В мире объект играет определенные роли, выполняя свои обязанности.
Активный объект имеет собственный канал (поток) управления, пассивный - нет. Активный объект автономен, он может проявлять свое поведение без воздействия со стороны других объектов. Пассивный объект, наоборот, может изменять свое состояние только под воздействием других объектов.
Виды отношений между объектами В поле зрения разработчика ПО находятся не объекты-одиночки, а взаимодействующие объекты, именно взаимодействие объектов реализует поведение системы. Г. Буч: «Самолет - это набор элементов, каждый из которых по своей природе стремится упасть на землю, но ценой совместных непрерывных усилий преодолевает эту тенденцию». Отношения между парой объектов основываются на взаимной информации о разрешенных операциях и ожидаемом поведении. Интересны два вида отношений между объектами: связи и агрегация.
Связи Связь - это физическое или понятийное соединение между объектами. Объект сотрудничает с другими объектами через соединяющие их связи. Связь обозначает соединение, с помощью которого: объект-клиент вызывает операции объекта- поставщика; один объект перемещает данные к другому объекту. Связи являются рельсами между станциями- объектами, по которым ездят «трамвайчики сообщений».
Как участник связи объект может играть одну из трех ролей: актер - объект, который может воздействовать на другие объекты, но никогда не подвержен воздействию других объектов; сервер - объект, который никогда не воздействует на другие объекты, он только используется другими объектами; агент - объект, который может как воздействовать на другие объекты, так и пользоваться ими. Агент создается для выполнения работы от имени актера или другого агента.
Агрегация Связи обозначают равноправные отношения между объектами. Агрегация обозначает отношения объектов в иерархии «целое/часть». Агрегация обеспечивает возможность перемещения от целого (агрегата) к его частям (свойствам). Агрегация может обозначать, а может и не обозначать физическое включение части в целое. При выборе вида отношения - учитывать факторы: связи обеспечивают низкое сцепление между объектами; агрегация инкапсулирует части как секреты целого.
Пример физического включения (композиции) частей (Двигателя, Сидений, Колес) в агрегат Автомобиль - части включены в агрегат по величине.
Пример нефизического включения частей (Студента, Преподавателя) в агрегат Вуз. Студент и Преподаватель являются элементами Вуза, но они не входят в него физически. Части включены в агрегат по ссылке.
Классы Классы – множества однотипных объектов с одинаковым поведением и набором атрибутов. У различных объектов одного класса различаются значения атрибутов, однако методы совпадают. Объекты называются экземплярами класса.
Различают внутреннее представление класса (реализацию) и внешнее представление класса (интерфейс). Интерфейс объявляет возможности (услуги) класса, но скрывает его структуру и поведение. Интерфейс состоит из объявлений всех операций, применимых к экземплярам класса. Он может включать объявления типов, переменных, констант и исключений, необходимых для полноты данной абстракции.
Интерфейс - 3 части: 1. публичная (public) - объявления доступны всем клиентам; 2. защищенная (protected) - объявления доступны только самому классу, его подклассам и друзьям; 3. приватная (private) - объявления доступны только самому классу и его друзьям. КЛАСС интерфейсные: Части Публичная Защищенная Приватная Реализация Друг класса - класс, который имеет доступ ко всем частям класса. От друга у класса нет секретов. Реализация класса описывает секреты поведения класса. Она включает реализации всех операций, определенных в интерфейсе класса.
Инкапсуляция Внутреннее состояние и поведение объекта скрыто от других объектов. Изменить его можно извне только с помощью передачи сообщения (вызова метода). В этом состоит принцип инкапсуляции. Метод, выполняемый в ответ на сообщение, определяется классом, которому принадлежит объект. Все экземпляры одного и того же класса используют одинаковые методы.
Позднее связывание. Полиморфизм. Имеется определенный объект, выполняющий метод Интерпретация сообщения (вызываемый метод) зависит от получателя и для разных объектов может быть разной. Обычно конкретный получатель неизвестен до выполнения программы, следовательно неизвестен метод, который будет вызван. В этом случае решение, какой метод вызывать, должно быть принято во время выполнения программы. Такой способ связи сообщения и метода называется поздним связыванием. Возможность объектов по- разному реагировать на одинаковые сообщения называется полиморфизм.
Иерархия наследования Классы могут быть организованы в иерархическую структуру с наследованием свойств. Дочерний класс (подкласс) наследует атрибуты родительского класса (надкласса), расположенного выше в иерархическом дереве. Объект Животное Трансп. средство Млекопитающее Человек Автомобиль Студент Техн. устройство Электронное устр. Монитор
Переопределение метода Поиск метода, который вызывается в ответ на определенное сообщение, начинается с методов, принадлежащих классу получателя. Если подходящий метод не найден, то поиск продолжается для родительского класса. Поиск продвигается вверх по цепочке родительских классов до тех пор, пока не будет найден нужный метод или пока не будет исчерпана последовательность родительских классов. В первом случае выполняется найденный метод, во втором - выдается сообщение об ошибке. Если выше в иерархии классов существуют методы с тем же именем, что и текущий, то говорят, что данный метод переопределяет наследуемое поведение. Возможность переопределения методов есть реализация полиморфизма.
Повторное использование Наследование позволяет различным типам данных совместно использовать один и тот же код, приводя к уменьшению его размера и повышению функциональности. Полиморфизм обеспечивает, чтобы общий код удовлетворял конкретным особенностям отдельных типов данных. В итоге становится возможным максимально использовать существующий код.
ОО программа Программа – совокупность взаимодействующих объектов. Каждый объект выполняет конкретную функцию. Объект соединяет вместе состояние (данные) и поведение (методы). Объекты одного класса имеют одни и те же методы. Объект проявляет свое поведение путем вызова метода в ответ на сообщение. Интерпретация сообщения зависит от объекта и может быть различной для различных классов объектов. Для удобства создания нового класса из уже существующих используется механизм наследования. Наследование обеспечивает повторное использование.
Принципы ООП Инкапсуляция (объединение данных с методами в сочетании со скрытием данных) Абстракция (расширяемость системы классов) Наследование (повторное использование методов и атрибутов) Полиморфизм (переопределение методов и гибкий выбор метода во время выполнения программы)
ООП в С++ Класс – тип данных, содержащий поля (переменные) и методы (функции) для их обработки. Объект – переменная типа класс. Отличия ООП в С++ от Delphi –статическое размещение объектов в памяти –неявный вызов конструкторов и деструкторов –перегрузка операций –множественное наследование –отсутствие свойств (property) –вложенность классов –отсутствие единого предка
Описание класса (без наследования) class { [private:] public: }; Элементы класса – поля и методы.
Пример класса #include class student { char fam[20],name[20]; int age; public: void setdata (char *f, char *n, int a = 20) { age = a; strcpy(fam, f); strcpy(name, n); } void show () { cout
Использование объектов int main () { student a, b ; a.setdata("Ivanov", "Boris"); b.setdata("Sokolova", "Olga", 19); a.show(); b.show(); return 0; } Описание объектов Вызов методов (передача сообщений)
Глобальные и локальные классы Классы могут быть глобальными (объявленными вне любого блока) и локальными (объявленными внутри блока, например, функции или класса). Локальные классы не могут иметь статических элементов, все методы должны быть описаны внутри класса.
Встроенные и обычные методы Встроенный метод определяется внутри класса. Метод может быть определен вне класса, тогда внутри класса указывается только его заголовок. class student { char fam[20],name[20]; int age; public: void setdata (char *f, char *n, int a = 20); void show (); };
Определение метода вне класса При определении метода вне класса в его заголовке указывается имя класса с использованием операции доступа к области видимости (::). void student :: setdata (char *f, char *n, int a) { age = a; strcpy(fam, f); strcpy(name, n); }
Примеры использования объектов student group [25]; student *s = new student; … for (int i = 0; i < 25; i++) group[i].show(); s -> setdata ( Sidorov, Ivan );
Указатель this Для того, чтобы метод работал с полями того объекта, для которого он вызван, передается скрытый параметр this, содержащий константный указатель на объект. В явном виде this используется для возврата ссылки или указателя на объект. student& student :: old (student &a) { if ( age > a.age ) return *this; return a; } … student c = a.old(b); c.show();
Конструкторы Конструктор – метод предназначенный для инициализации объекта, выполняющийся автоматически в момент его создания. Конструктор имеет имя, совпадающее с именем класса. Конструктор не возвращает значение. Класс может иметь несколько перегруженных конструкторов с разными параметрами. Конструктор по умолчанию – не имеет параметров. Для любого класса автоматически создается такой конструктор. Конструктор может иметь параметры со значениями по умолчанию.
Пример использования конструктора #include class _time { int h,m; public: _time ( int hours = 0, int minutes = 0) { h = hours; m = minutes; } void show() { cout
Список инициализации Служит для инициализации полей в конструкторе. Список позволяет инициализировать константные поля и поля-ссылки class _time { int h,m; public: _time ( int hours = 0, int minutes = 0) : h( hours ), m ( minutes ) { } … };
Конструктор копирования Конструктор копирования получает в качестве параметра константную ссылку на объект того же класса. T (const T& ) Этот конструктор вызывается при описании объекта с инициализацией другим объектом при передаче объекта в функцию по значению при возврате объекта из функции Если конструктор копирования не указан, он будет создан автоматически.
Пример использования конструктора копирования class student { char *fam,*name; int age; public: student (char *f, char *n, int a = 20) : age (a) { fam = new char [20]; name = new char [20]; strcpy (fam, f); strcpy (name, n); } student (student &s) : age (s.age) { fam = new char [20]; name = new char [20]; strcpy (fam, s.fam); strcpy (name, s.name); } void show (); }; int main () { student a("Ivanov", "Boris"), b("Sokolova", "Olga", 19); student c = a; a.show(); b.show(); c.show(); return 0; }
Объекты как параметры функций Рассмотрим метод для сложения времени class _time { … void add (const _time &time1, const _time &time2) { h = time1. h + time2.h; m = time1. m + time2.m; if (m >= 60) { h++; m-=60;} h = h % 24;} }; Вызов: c.add( a, b);
Объекты как результаты функций _time inc ( _time interv) { _time t; t.h = h + interv.h; t.m = m + interv.m; if (t.m>=60) { t.h++; t.m- =60;} t.h = t.h % 24; return t; } Вызов: _time c = a.inc(b);
Деструкторы ~ class student { char *fam,*name; int age; public: … ~student() { delete [] name; delete [] fam;} }; int main () { student a("Ivanov", "Boris"), b("Sokolova", "Olga", 19); student c = a; a.show(); b.show(); c.show(); return 0; }