Автор Анна Евкова
Преподаватель который помогает студентам и школьникам в учёбе.

История и развитие методологии объектно-ориентированного программирования. Сферы применения)

Содержание:

Введение

Предметом исследований настоящей работы являются история и методология (учение о методах, способах и стратегиях исследования предмета) объектно-ориентированного программирования, сферы применения.

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

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

Основоположниками ООП являются создатели языка Simula – Нюгорт и Оле Джохан Дал. История Симулы началась в 1962 года с проекта Simulation Language. Одновременно готовились две версии. Прародителем первой стал Алгол 60. Вторая была выбрана благодаря блочной архитектуре, сокрытию данных и высокой популярности.

В 1965 году авторы решили объединить данные с процедурами, их обрабатывающими. В язык вошли новые средства моделирования и имитации мультипроцессной работы. Были сформулированы термины “класс” и “объект”, введена технология наследования.

Новая версия языка была закончена в 1967 году. Он поддерживал проектирование “сверху вниз” с помощью виртуальных процедур и технологии статического и динамического связывания. Также Якоб Пелме добавил механизм сокрытия переменных. Первый законченный компилятор Симулы 67 увидел свет в 1969 году.

Тем временем Алан Кей изучал идеи, заложенные в Simula, Lisp и Logo. В ходе ознакомления он придумал концепцию разработки, в соответствии с которой набор последовательно выполняющихся инструкций мог быть заменен на многомерную среду взаимодействия объектов, общающихся друг с другом путем асинхронного обмена сообщениями.

Свои идеи он смог воплотить в новом языке SmallTalk, смоделированном на Бейсике, и реализованном на ассемблере. В процессе работы Алан предложил всем знакомый термин “объектно-ориентированное программирование” (ООП).

Превзойти популярность Си Smalltalk так и не смог. Этот язык, придуманный Кеном Томпсоном и Деннисом Ритчи, добрался до ООП своим путем.

1974 год. Марвин Мински предложил идею фрейма, отделившего описание структуры объекта от его экземпляра. Фрейм стал предшественником понятия объектов в Си++

1976 год. Кинстен Нюгорн создал новый язык BETA и ввел концепцию шаблонов – более высокого уровня абстракций, в отличие от объектов.

1980 год. Бьерн Страуструп дополнил язык Си концепцией классов, основанной на фреймах и объектных механизмах Симулы. Позднее, в 1983, он дал своему творении. Окончательное название – Си++.

Первая всемирная конференция по объектно-ориентированным системам программирования, прошедшая в 1986 в Портленде, оказала влияние на Уильяма Аткинсона, инженера Apple. Через год он спроектировал систему HyperCard, которая дала начало современным визуальным средам быстрой разработки. Эффективность новой технологии оказалась настолько велика, что уже в 1989 году одиннадцать компаний основали группу OMG (Object Management Group). И первым делом она начала выработку стандарта компонентной модели CORBA (Common Object Request Broker Architecture) – набора спецификаций, определяющих способы объектно-ориентированного взаимодействия компонентов промежуточного уровня в гетерогенных средах без привязки к конкретным языкам программирования[1].

В 1992 году вышел стандарт CORBA 1.0, определяющий ключевые аспекты функционирования CORBA-систем. В него вошли: базовое описание объектной модели, наборы программных интерфейсов поддержки, декларативный язык определения интерфейсов Interface Definition Language (IDL).

1994 год, Стандарт CORBA 2.0, в котором были исправлены недостатки. Как результат – поддерживание транзакции и понимание кодировки Unicode.

Гради Буч и Джеймс Румбах решили объединить Booch и OMT и создать на их основе новый язык – UML (Unified Modeling Language).

А в 1995 Sun Microsystems идет распространение в сети Java.

Эксперты OMG осознают не только важность объектных технологий программирования, но и острую потребность в универсальных методологических концепциях проектирования крупных систем. Секретом стабильности системы и высокой отдачи инвестиций специалисты OMG называют независимую UML-модель и приступают к созданию концепции "Архитектура, управляемая моделью" (Model Driven Architecture, MDA). В ее основу закладывается базовая платформно-независимая UML-модель системы, несколько платформно-зависимых моделей и коллекция определений программных интерфейсов. Первую реализацию этой универсальной концепции (так называемое "отображение в объектный стандарт") OMG выполнила, конечно, для CORBA.

2000 год. Microsoft анонсирует новую объектную платформу .NET и новый язык программирования C#, сочетающий лучшие свойства С++ и Java. Он был предложен Microsoft во многом в противовес Java.

В своей курсовой работе я хочу подробнее рассказать о сложности программного обеспечения, истории и методах, способах и стратегиях исследования объектно-ориентированного программирования, сферах применения.

1. СЛОЖНОСТЬ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ

Объектно-ориентированный подход возник в первую очередь в ответ на растущую сложность программного обеспечения. На заре компьютерной эры возможности компьютеров были ограничены и было очень трудно написать большую программу. В 60–70-е гг. использование компьютеров в повседневной жизни возросло, и стало все больше создаваться прикладных программ повышенной сложности. Наибольшее распространение в это время получило структурное проектирование по методу сверху вниз. Однако через некоторое время оказалось, что структурный подход не работает, если объем программы превышает приблизительно 100 тыс. строк. Как результат – выход проектов за рамки установленных сроков и бюджетов и их несоответствие начальным требованиям. Для решения этих проблем и стали применять объектно-ориентированный подход.

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

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

Сложность является существенной чертой промышленной программы: один разработчик практически не в состоянии охватить все аспекты такой системы. Фактически сложность промышленных программ превышает возможности интеллекта одного человека.

Сложность, присущая программному обеспечению, определяется следующими основными причинами: сложностью реального мира; сложностью управления процессом разработки; гибкостью программного обеспечения; сложностью описания поведения систем.

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

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

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

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

Гибкость программного обеспечения - Программирование обладает максимальной гибкостью среди технических наук. Программист, как и писатель, работает со словом, и всеми базовыми элементами, необходимыми для создания программ, он может обеспечить себя сам, зачастую пренебрегая уже существующими разработками. Такая гибкость – чрезвычайно привлекательное, но опасное качество: пользователь, осознав эту возможность, постоянно изменяет свои требования; разработчик увлекается украшательством своей системы во вред основному ее назначению. Поэтому программные разработки остаются очень кропотливым и "бесконечным" делом, а программные системы потенциально незавершенными[3].

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

Любая сложная система, в том числе и сложная программная система, обладает следующими общими признаками[4]:

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

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

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

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

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

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

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

4. Иерархические системы обычно состоят из немногих типов подсистем, по-разному скомбинированных и организованных.

Иными словами, разные сложные системы содержат одинаковые структурные части. Эти части, в свою очередь, могут использовать общие более мелкие компоненты. Например, и у растений, и у животных имеются крупные подсистемы типа сосудистых систем, и клетки как более мелкие компоненты.

5. Любая работающая сложная система является результатом развития работавшей более простой системы.

В качестве примера назовем теорию эволюции живой природы.

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

В процессе развития системы объекты, первоначально рассматривавшиеся как сложные, становятся элементарными, и из них строятся более сложные системы.

2. ОБЪЕКТНАЯ МОДЕЛЬ

Объектно-ориентированный подход основывается на совокупности ряда принципов, называемой объектной моделью. Главными принципами являются[5]: абстрагирование; инкапсуляция; модульность; иерархичность.

Кроме главных, есть еще три дополнительных принципа: типизация; параллелизм; сохраняемость.

2.1. Абстрагирование

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

Например, изучая процесс фотосинтеза у растений, мы концентрируем внимание на химических реакциях в определенных клетках листа и не обращаем на остальные части – черенки, жилки и т.д.

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

Абстрагирование концентрирует внимание на внешних особенностях объекта и позволяет отделить самые существенные особенности поведения от несущественных. Такое разделение смысла и реализации называют барьером абстракции. Установление того или иного барьера абстракции порождает множество различных абстракций для одного и того же предмета или явления реального мира. Абстрагируясь в большей или меньшей степени от различных аспектов проявления реальности, мы находимся на разных уровнях абстракции[6].

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

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

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

Все абстракции обладают как статическими, так и динамическими свойствами. Например, файл как объект требует определенного объема памяти на конкретном устройстве, имеет имя и содержимое. Эти атрибуты являются статическими свойствами. Конкретные же значения каждого из перечисленных свойств динамичны и изменяются в процессе использования объекта: файл можно увеличить или уменьшить, изменить его имя и содержимое.

Будем называть клиентом любой объект, использующий ресурсы другого объекта, называемого сервером. Мы будем характеризовать поведение объекта услугами, которые он оказывает другим объектам, и операциями, которые он выполняет над другими объектами. Этот подход концентрирует внимание на внешних проявлениях объекта и реализует так называемую контрактную модель программирования. Эта модель заключается в следующем: внешнее проявление объекта рассматривается с точки зрения его контракта с другими объектами, в соответствии с этим должно быть выполнено и его внутреннее устройство (часто – во взаимодействии с другими объектами). Контракт фиксирует все обязательства, которые объект-сервер имеет перед объектом-клиентом. Другими словами, этот контракт определяет ответственность объекта – то поведение, за которое он отвечает.

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

Пример. В тепличном хозяйстве, использующем гидропонику, растения выращиваются на питательном растворе без песка, гравия и другой почвы. Управление режимом работы парниковой установки – очень ответственное дело. Оно зависит как от вида выращиваемых культур, так и от стадии выращивания. Нужно контролировать целый ряд факторов: температуру, влажность, освещение, кислотность и концентрацию питательных веществ. В больших хозяйствах для решения этой задачи часто используют автоматические системы, которые контролируют и регулируют указанные факторы. Цель автоматизации состоит здесь в том, чтобы при минимальном вмешательстве человека добиться соблюдения режима выращивания.

Одна из ключевых абстракций в данной задаче – датчик. Известно несколько разновидностей датчиков. Все, что влияет на урожай, должно быть измерено. Таким образом, нужны датчики температуры воды, температуры воздуха, влажности, кислотности, освещения и концентрации питательных веществ.

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

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

Абстракция и инкапсуляция дополняют друг друга: абстрагирование направлено на наблюдаемое поведение объекта, а инкапсуляция занимается внутренним устройством. Инкапсуляция выполняется посредством скрытия информации, т.е. маскировкой всех внутренних деталей, не влияющих на внешнее поведение. Обычно скрываются и внутренняя структура объекта, и реализация его операций. Для скрытия информации многие объектно-ориентированные языки программирования имеют соответствующие механизмы.

В результате возникает необходимость рассмотреть понятия интерфейса и реализации. Интерфейс – это набор операций, используемый для специфицирования услуг, предоставляемых классом. Интерфейс отражает внешнее поведение объекта. Внутренняя реализация описывает представление этой абстракции и механизмы достижения желаемого поведения объекта.

Интерфейс стека – это его операции pop и push, а реализация – это конкретное представление стека.

Друзьями класса называются классы или операции, имеющие доступ к закрытым операциям или данным некоторого класса.

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

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

Сокрытие информации – понятие относительное: то, что спрятано на одном уровне абстракции, обнаруживается на другом уровне. Кроме того, на практике иногда необходимо ознакомиться с реализацией класса, чтобы понять его назначение.

2.3. Модульность

Модулем называют набор связанных процедур вместе с данными, которые они обрабатывают.

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

Пример[8]. В качестве примера рассмотрим модульную структуру программы, использующей стек.

Реализация стека и код пользователя будут находиться в раздельно компилируемых частях программы.

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

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

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

В объектно-ориентированном программировании по модулям необходимо распределить классы и объекты.

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

Рассмотрим приемы и правила, которые позволяют составлять модули наиболее эффективным образом:

– конечной целью разбиения программы на модули является снижение затрат на программирование за счет разработки и тестирования;

– структура модуля должна быть достаточно простой для восприятия;

– реализация каждого модуля не должна зависеть от реализации других модулей;

– должны быть приняты меры для облегчения процесса внесения изменений там, где они наиболее вероятны.

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

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

На выбор разбиения на модули могут влиять и внешние обстоятельства, требования секретности.

Итак, модульность – это свойство системы, которая была разложена на внутренне связные, но слабо связанные между собой модули.

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

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

2.4. Иерархичность

Значительное упрощение в понимании сложных задач достигается за счет образования из абстракций иерархической структуры.

Иерархия – это упорядочение абстракций, расположение их по уровням. Основными видами иерархических структур применительно к сложным системам являются иерархии типа "является" и иерархии типа "имеет".

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

Например, лазерный принтер является разновидностью принтеров (лазерный принтер является принтером), принтер Хьюлет-Паккард 6L является разновидностью лазерных принтеров (принтер Хьюлет-Паккард 6L является лазерным принтером). Понятие "принтер" обобщает свойства, присущие всем принтерам, а лазерный принтер – это просто особый тип принтера со свойствами, которые отличают его, например, от матричного или струйного принтера.

Важный элемент объектно-ориентированных систем и основной вид иерархии "является" – иерархия обобщения (наследования) (отношение родитель-потомок).

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

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

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

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

Пример. Одиночное наследование. Вернемся к иерархии "принтер – лазерный принтер" (лазерный принтер является разновидностью принтеров).

Абстракция "лазерный принтер" строится на основе родительской абстракции "принтер". "Лазерный принтер" наследует от "принтера" свойства, определяющие все принтера. Кроме того, лазерный принтер имеет структурные и функциональные части, реализующие свойства, которые характерны именно для лазерных принтеров.

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

Множественным наследованием часто злоупотребляют. Например, сладкая вата – это частный случай сладости, но никак не ваты. Следует применять ту же "лакмусовую бумажку": если В не есть А, то ему не стоит наследовать от А[9].

Иерархия "имеет" вводит отношение агрегации (целое/часть). В иерархии "имеет" некоторая абстракция находится на более высоком уровне, чем любая из использованных при ее реализации.

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

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

2.5. Типизация

Типизация – это способ защититься от использования объектов одного класса (типа) вместо другого, или, по крайней мере, управлять таким использованием.

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

Важным понятием объектно-ориентированного подхода в целом является полиморфизм.

Полиморфизм – это способ присваивать различные значения (смыслы) одному и тому же сообщению. Смысл зависит от типа обрабатываемых данных.

Имеется несколько типов полиморфизма.

Принудительное приведение. Функция или оператор работает с несколькими различными типами, преобразуя их значения к требуемому типу.

Перегрузка. Функция или оператор вызывается на основе сигнатуры.

Если в описание класса ввести определение функции-члена с именем типа "operator оператор", то это означает, что данный оператор может быть применен к объектам или объекту данного класса, так же как и к переменным стандартных типов. При этом тело данной функции определяет смысл оператора.

Есть другие типы полиморфизма – включение и параметрический полиморфизм. Для осуществления явных преобразований переменных одного типа к другому типу имеются специальные операторы приведения.

2.6. Параллелизм

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

Процесс (поток управления) – это фундаментальная единица действия в системе. Каждая программа имеет, по крайней мере, один поток управления, в параллельной системе таких потоков много.

Век одних потоков недолог, а другие живут в течение всего сеанса работы системы.

Параллелизм главное внимание уделяет абстрагированию и синхронизации процессов.

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

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

Параллелизм – это свойство, отличающее активные объекты от неактивных.

2.7. Сохраняемость

Любой программный объект существует в памяти и живет во времени.

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

По традиции, первыми тремя уровнями занимаются языки программирования, а последними – базы данных. Языки программирования, как правило, не поддерживают понятия сохраняемости. Можно записывать объекты в неструктурированные файлы, но этот подход пригоден только для небольших систем. Как правило, сохраняемость достигается применением специальных объектно-ориентированных баз данных.

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

Итак, сохраняемость – это способность объекта существовать во времени, переживая породивший его процесс, и (или) в пространстве, перемещаясь из своего первоначального адресного пространства.

3. ОБЪЕКТЫ

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

3.1. Состояние

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

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

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

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

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

Перечень свойств объекта является, как правило, статическим, поскольку эти свойства составляют неизменяемую основу объекта.

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

3.2. Поведение

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

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

Операция – это услуга, которую можно запросить у любого объекта класса для воздействия на его поведение.

Например, клиент может активизировать операции push и pop для того, чтобы управлять объектом-стеком (добавить или изъять элемент).

В чисто объектно-ориентированном языке принято говорить о передаче сообщений между объектами. В C++ мы говорим, что один объект вызывает функцию-член другого. В основном понятие сообщение совпадает с понятием операции над объектами[11].

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

Рассмотрим торговый автомат. Мы можем сделать выбор, но поведение автомата будет зависеть от его состояния. Если мы не опустили в него достаточную сумму, скорее всего ничего не произойдет. Если же денег достаточно, автомат выдаст нам желаемое (и тем самым изменит свое состояние).

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

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

– модификатор – это операция, которая изменяет состояние объекта;

– селектор – это операция, считывающая состояние объекта, но не меняющая состояния;

– конструктор – это операция создания объекта и/или его инициализации;

– деструктор – это операция, освобождающая ресурсы, которые использует объект, и/или разрушающая сам объект.

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

Объекты могут создаваться следующим образом: автоматический объект создается каждый раз, когда его описание встречается при выполнении программы, и уничтожается каждый раз при выходе из блока, в котором оно появилось; статический объект создается один раз, при запуске программы, и уничтожается один раз, при ее завершении; объект в свободной памяти создается с помощью операции new и уничтожается с помощью операции delete; объект-член создается как подобъект другого класса.

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

В чисто объектно-ориентированных языках определять процедуры и функции вне классов не допускается.

Операции, определенные вне классов, называют свободными подпрограммами.

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

3.3. Идентичность

Идентичность – это такое свойство объекта, которое отличает его от всех других объектов.

Источником ошибок в объектно-ориентированном программировании является неумение отличать имя объекта от самого объекта.

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

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

3.4. Отношения между объектами

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

Отношения двух любых объектов основываются на предположениях, которыми один обладает относительно другого: об операциях, которые можно выполнять, и об ожидаемом поведении.

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

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

Пусть есть два объекта А и В и связь между ними. Чтобы А мог послать В сообщение, В должен быть в каком-то смысле видим для А.

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

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

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

4. КЛАССЫ

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

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

Пример. Рассмотрим сходства и различия между следующими классами: цветы, маргаритки, красные розы, желтые розы, лепестки и пчелы. Мы можем заметить следующее: маргаритка – цветок; роза – (другой) цветок; – красная и желтая розы – розы; лепесток является частью обоих видов цветов; пчелы опыляют цветы и питаются их нектаром.

Из этого простого примера следует, что классы, как и объекты, не существуют изолированно. В каждой проблемной области абстракции, описывающие ее, взаимодействуют различными способами.

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

4.1. Ассоциация

Ассоциация – смысловая связь. По умолчанию, она не имеет направления и не объясняет, как классы общаются друг с другом. Мы можем только отметить семантическую зависимость, указав, какие роли играют классы друг для друга.

Так, ассоциация "Product – Sale" – двустороннее отношение: задавшись товаром, можно выйти на сделку, в которой он был продан, а пойдя от сделки, найти, что было продано[12].

Кратность (мощность) ассоциации – это количество ее участников. Различают три случая кратности ассоциации: один-к-одному; один-ко-многим; многие-ко-многим.

Рассмотренная в примере ассоциация имеет тип один-ко-многим: каждый экземпляр товара относится только к одной последней продаже, в то время как каждый экземпляр Sale может указывать на совокупность проданных товаров.

Отношение один-к-одному обозначает очень узкую ассоциацию. Например, в розничной системе продаж примером могла бы быть связь между классом "Продажа" и классом "Снятие денег с кредитной карточки": каждая продажа соответствует ровно одному снятию денег с данной кредитной карточки.

Отношение многие-ко-многим тоже нередко. Например, каждый объект класса "Покупатель" может инициировать сделку с несколькими объектами класса "Торговый агент", и каждый "Торговый агент" может взаимодействовать с несколькими объектами класса "Покупатель".

Класс может иметь ассоциацию с самим собой. Такая ассоциация называется рефлексивной.

4.2. Агрегация

Агрегация является частным случаем ассоциации. Отношение агрегации между классами имеет непосредственное отношение к агрегации между их экземплярами.

Пример. Вернемся к классу Controller, который является абстракцией объектов, управляющих температурой в теплице ( п. 2.1 настоящей работы).

Класс Controller – это целое, а экземпляр класса Heater (нагреватель) – одна из его частей. В рассмотренном случае мы имеем специальный случай агрегации – композицию.

Композиция – форма агрегирования, в которой целое владеет своими частями, имеющими одинаковое с ним время жизни. Части с нефиксированной кратностью могут быть созданы после создания агрегата, но, будучи созданными, живут и умирают вместе с ним. Такие части могут также быть явно удалены перед уничтожением агрегата. В случае композитного агрегирования объект в любой момент времени может быть частью только одного композита.

4.3. Обобщение

Обобщение (наследование) – это такое отношение между классами, когда один класс повторяет структуру и поведение другого класса (одиночное наследование) или других классов (множественное наследование).

Для описания полиморфизма используются два различных понятия: операция и метод. У класса есть операции, которые определяют его поведение, и методы – реализации данных операций. При этом каждый потомок класса может предоставить метод, реализующий любую унаследованную операцию, отличный от соответствующего метода предка. Чисто виртуальная функция (абстрактная операция) не имеет соответствующего метода.

Самый общий класс в иерархии классов называется базовым. В большинстве приложений базовых классов бывает несколько, и они отражают наиболее общие абстракции предметной области.

У класса обычно бывает два вида клиентов: экземпляры классов и подклассы. Часто полезно иметь для них разные интерфейсы. В частности, мы хотим показать только внешне видимое поведение для клиентов-экземпляров, но нам нужно открыть служебные функции и представления клиентам-подклассам.

Для этой цели описание класса разделяется на три части: открытую (public), видимую всем клиентам; защищенную (protected), видимую самому классу, его подклассам и друзьям (friend); закрытую (private), видимую только самому классу и его друзьям.

Вопросы построения наследственных иерархий тесно связаны с типизацией (в языках с сильной типизацией), поскольку при использовании наследования формируется и система типов.

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

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

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

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

Рассмотрим две проблемы, которые возникают при множественном наследовании: конфликт имен между суперклассами и повторное наследование.

Конфликт имен происходит тогда, когда в двух или более суперклассах случайно оказывается элемент (переменная или операция) с одинаковым именем.

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

Одним из механизмов задания совместного использования является виртуальный базовый класс. Виртуальный базовый класс в производном классе представлен одним и тем же (совместно используемым) объектом.

4.4. Зависимость

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

Один класс может использовать другой по-разному. В моем примере это происходит при описании интерфейсной функции. Отношение использования также имеет место, если в реализации какой-либо операции происходит объявление локального объекта используемого класса.

4.5. Инстанцирование

Инстанцирование – подстановка фактических параметров шаблона на место формальных. В результате создается конкретный класс, который может иметь экземпляры. Инстанцирование безопасно с точки зрения типов.

4.6. Переменные и операции класса

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

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

4.7. Интерфейсы

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

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

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


4.8 Группирование классов

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

Пакет не имеет операций или состояний в явном виде, они содержатся в нем неявно в описаниях агрегированных классов.

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

Заключение

Основные выводы по работе.

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

Объектно-ориентированный подход основывается на определенных принципах: абстрагирование, инкапсуляция, модульность, иерархичность (главные); типизация, параллелизм, сохраняемость (дополнительные).

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

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

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

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

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

Идентичность – это такое свойство объекта, которое отличает его от всех других объектов.

Отношения двух любых объектов основываются на предположениях, которыми один обладает относительно другого: об операциях, которые можно выполнять, и об ожидаемом поведении.

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

Структура и поведение схожих объектов определяет общий для них класс.

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

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

Литература

  1. Сергей Бобровский. История объектно-ориентированного программирования. http://www.info-system.ru/retro/po/po_object_prog.htm
  2. Бадд Т. Объектно-ориентированное программирование в действии. СПб.: "Питер", 1997.
  3. Буч Г. Объектно-ориентированное проектирование с примерами применения. – М.: Конкорд, 1992.
  4. Пол А. Объектно-ориентированное программирование на С++. – СПб.; М.: "Невский диалект" – "Издательство Бином", 1999.
  5. Фридман А.Л. Основы объектно-ориентированной разработки программных систем. – М.: Финансы и статистика, 2000
  1. Сергей Бобровский. История объектно-ориентированного программирования

  2. Буч Г. Объектно-ориентированное проектирование с примерами применения

  3. Фридман А.Л. Основы объектно-ориентированной разработки программных систем

  4. Бадд Т. Объектно-ориентированное программирование в действии.

  5. Пол А. Объектно-ориентированное программирование на С++.

  6. Фридман А.Л. Основы объектно-ориентированной разработки программных систем

  7. Буч Г. Объектно-ориентированное проектирование с примерами применения.

  8. диапазон значений и определенную точность и означающий число градусов по Цельсию.

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

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

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

    Центральной идеей абстракции является понятие инварианта. Инвариант – это некоторое логическое условие, значение которого (истина или ложь) должно сохраняться. Для каждой операции объекта можно задать предусловия (т.е. инварианты, предполагаемые операцией) и постусловия (т.е. инварианты, которым удовлетворяет операция).

    Рассмотрим инварианты, связанные с операцией currentTemperature. Предусловие включает предположение, что датчик установлен в правильном месте в теплице, а постусловие – что датчик возвращает значение температуры в градусах Цельсия.

    Изменение инварианта нарушает контракт, связанный с абстракцией. Если нарушено предусловие, то клиент не соблюдает свои обязательства и сервер не может выполнить задачу правильно. Если нарушено постусловие, то свои обязательства нарушил сервер, и клиент не может ему больше доверять.

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

    2.2. Инкапсуляция

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

    На самом деле клиента не интересует, и не должно интересовать то, как реализовано выполнение контрактных обязательств. По крайней мере, пока сервер соблюдает свои обязательства.

    Пример?. Для программиста, использующего стек, важно только то, что он может помещать и извлекать нужные ему объекты с помощью ? Буч Г. Объектно-ориентированное проектирование с примерами применения

  9. Бадд Т. Объектно-ориентированное программирование в действии

  10. Буч Г. Объектно-ориентированное проектирование с примерами применения

  11. Пол А. Объектно-ориентированное программирование на С++

  12. Фридман А.Л. Основы объектно-ориентированной разработки программных систем