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

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

Содержание:

Введение

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

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

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

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

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

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

Иерархия - это ранжирование или упорядочение абстракций.

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

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

Сохраняемость - способность объекта существовать во времени и (или) в пространстве.

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

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

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

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

В данном определении можно выделить три части: 1) OOP использует в качестве базовых элементов объекты, а не алгоритмы (иерархия "быть частью", которая была определена в главе 1); 2) каждый объект является экземпляром какого-либо определенного класса; 3) классы организованы иерархически.

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

В соответствии с этим определением не все языки программирования являются объектно-ориентированными.

Карделли и Вегнер говорят, что: "язык программирования является объектно-ориентированным тогда и только тогда, когда выполняются следующие условия:

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

- Объекты относятся к соответствующим типам (классам).

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

Карделли и Вегнер назвали такие языки объектными, но не объектно-ориентированными. 

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

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

1.1 История и развитие

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

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

История Симулы началась в 1962 г. с проекта Simulation Language, предназначенного для программного моделирования метода Монте-Карло.

Нюгорт, занимавший в то время должность директора по науке Норвежского компьютерного центра (NCC), приступил к созданию языка дискретного моделирования в результате прародителем Симулы стал Алгол 60.

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

В язык вошли новые средства моделирования и имитации мультипроцессной работы. Авторы также придумали термины "класс" и "объект".

Тогда же возникла и технология наследования - создатели Симулы ввели в язык возможность использования разными классами.

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

В NCC была сформирована рабочая группа Simula Standards Group. общих свойств путем указания названия класса в виде префикса.

Позже Кей перешел в Стэнфордскую лабораторию по искусственному интеллекту, а в 1972 г. устроился на работу в хорошо известный научный центр Xerox PARC, где и воплотил эти идеи в новом объектном языке SmallTalk, первоначально названном им Biological System и смоделированном на Бейсике, а затем реализованном на ассемблере.

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

1.2 Объектная модель

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

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

- абстрагирование;

- инкапсуляция;

- модульность;

- иерархия.

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

- типизация;

- параллелизм;

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

Называя их дополнительными, мы имеем в виду, что они полезны в объектной модели, но не обязательны.

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

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

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

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

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

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

Инвариантэто некоторое логическое условие, значение которого (истина или ложь) должно сохраняться.

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

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

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

Примеры

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

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

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

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

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

Что такое температура? Это числовой параметр, имеющий ограниченный диапазон значений и определенную точность, означающий число градусов по Фаренгейту, Цельсию или Кельвину.

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

Теперь можно задать вопрос о том, каковы обязанности датчика температуры? Мы решаем, что датчик должен знать температуру в своем местонахождении и сообщать ее по запросу.

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

Итак, вот описания, задающие абстрактный датчик температуры на C++.

//Температура по Фаренгейту 
typedef float Temperature;

// Число, однозначно определяющее положение датчика 
typedef unsigned int Location;

class TemperatureSensor {

public:

TemperatureSensor (Location);

~TemperatureSensor();

void calibrate(Temperature actualTemperature);

Temperature currentTemperature() const;

private: 
... 
};

1.4 Инкапсуляция

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

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

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

Рассмотрим пример с классом «Легковой автомобиль», нетрудно проиллюстрировать инкапсуляцию следующим образом.

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

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

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

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

Примеры

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

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

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

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

Как всегда, начнем с типов.

//Булевский тип 
enum Boolean {FALSE, TRUE};

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

Итак, вот класс Heater для абстрактных нагревателей, написанный на C++:

class Heater { 
public:

Heater(Location); 
~Heater(); 
void turnOn(); 
void tum0ff(); 
Boolean is0n() const;

private: 
};

1.5 Полиморфизм

Под полиморфизмом (греч. Poly– много, morfos – форма) понимают свойство некоторых объектов принимать различные внешние формы в зависимости от обстоятельств.

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

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

Примеры

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

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

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

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

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

1.6 Модульность

Модульность - это разделение программы на фрагменты, которые компилируются по отдельности, но могут устанавливать связи с другими модулями.

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

В разных языках программирования модульность поддерживается по-разному. Например, в C++ модулями являются раздельно компилируемые файлы. Для C/C++ традиционным является помещение интерфейсной части модулей в отдельные файлы с расширением .h (так называемые файлы-заголовки). 

Реализация, то есть текст модуля, хранится в файлах с расширением .с (в программах на C++ часто используются расширения .ее, .ср и .срр). Связь между файлами объявляется директивой макропроцессора #include. Такой подход строится исключительно на соглашении и не является строгим требованием самого языка.

В языке Object Pascal принцип модульности формализован несколько строже. В этом языке определен особый синтаксис для интерфейсной части и реализации модуля (unit).

Язык Ada идет еще на шаг дальше: модуль (называемый package) также имеет две части - спецификацию и тело. Но, в отличие от Object Pascal, допускается раздельное определение связей с модулями для спецификации и тела пакета.

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

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

Логика электронного оборудования может быть построена на основе элементарных схем типа НЕ, И-НЕ, ИЛИ-НЕ, но можно объединить такие схемы в стандартные интегральные схемы (модули), например, серий 7400, 7402 или 7404.

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

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

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

Примеры

Посмотрим, как реализуется модульность в гидропонной огородной системе. Допустим, вместо закупки специализированного аппаратного обеспечения, решено использовать стандартную рабочую станцию с графическим интерфейсом пользователя GUI (Graphical User Interface). С помощью рабочей станции оператор может формировать новые планы выращивания, модифицировать имеющиеся планы и наблюдать за их исполнением. Так как абстракция плана выращивания - одна из ключевых, создадим модуль, содержащий все, относящееся к плану выращивания. На C++ нам понадобится примерно такой файл-заголовок (пусть он называется gplan.h).

// gplan.h

#ifndef _GPLAN_H

#define _GPLAN_H 1 
#include "gtypes.h" 
#include "except.h" 
#include "actions.h" 
class GrowingPlan ... 
class FruitGrowingPlan ... 
class GrainGrowingPlan ...

#endif

1.7 Иерархия

Иерархия - это упорядочение абстракций, расположение их по уровням.

Основными видами иерархических структур применительно к сложным системам являются структура классов (иерархия "is-a") и структура объектов (иерархия "part of").

Примеры иерархии: одиночное наследование. Важным элементом объектно-ориентированных систем и основным видом иерархии "is-a" является упоминавшаяся выше концепция наследования.

Наследование означает такое отношение между классами (отношение родитель/потомок), когда один класс заимствует структурную или функциональную часть одного или нескольких других классов (соответственно, одиночное и множественное наследование).

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

Семантически, наследование описывает отношение типа "is-a". Например, медведь есть млекопитающее, дом есть недвижимость и "быстрая сортировка" есть сортирующий алгоритм.

Таким образом, наследование порождает иерархию "обобщение-специализация", в которой подкласс представляет собой специализированный частный случай своего суперкласса. "Лакмусовая бумажка" наследования - обратная проверка; так, если B не есть A, то B не стоит производить от A.

Примеры

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

// Тип Урожай 
typedef unsigned int Yield;

class FruitGrowingPlan : public GrowingPlan { 
public:

FruitGrowingPlan(char* name); 
virtual ~FruitGrowingPlan(); 
virtual void establish(Day, Hour, Condition&); 
void scheduleHarvest(Day, Hour); 
Boolean isHarvested() const; 
unsigned daysUntilHarvest() const; 
Yield estimatedYield() const;

protected:

Boolean repHarvested; 
Yield repYield;

1.8 Типизация

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

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

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

Примеры

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

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

// Число, обозначающее уровень от 0 до 100 процентов 
typedef float Level;

Построим теперь иерархию классов для емкостей:

Class StorageTank { 
public:

StorageTank(); 
virtual ~StorageTank(); 
virtual void fill(); 
virtual void startDraining(); 
virtual void stopDraining(); 
Boolean isEmpty() const; 
Level level() const;

protected: 
... 
};

class WaterTank : public StorageTank{ 
public:

WaterTank(); 
virtual ~WaterTank(); 
virtual void fill(); 
virtual void startDraining(); 
virtual void stopDraining(); 
void startHeating(); 
void stopHeating(); 
Temperature currentTemperature() const;

protected: 
... 
};

class NutrientTank : public StorageTank { 
public:

NutrientTank(); 
virtual ~NutrientTank(); 
virtual void startDrainingt(); 
virtual void stopDraining();

protected: 
... 
};

Класс StorageTank - это базовый класс иерархии. Он обеспечивает структуру и поведение общие для всех емкостей: возможность их наполнять или опустошать. Классы WaterTank (емкость для воды) и NutrientTank (для удобрений) наследуют свойства StorageTank, частично переопределяют их и добавляют кое-что свое: например, класс WaterTank вводит новое поведение, связанное с температурой.

1.9 Параллелизм

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

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

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

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

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

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

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

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

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

"Легкие" сосуществуют в одном адресном пространстве. "Тяжелые" процессы общаются друг с другом через операционную систему, что обычно медленно и накладно.

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

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

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

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

Примеры

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

Во-первых, параллелизм - это внутреннее свойство некоторых языков программирования. Так, для языка Ada механизм параллельных процессов реализуется как задача. В Smalltalk есть класс process, которому наследуют все активные объекты. Есть много других языков со встроенными механизмами для параллельного выполнения и синхронизации процессов - Actors, Orient 84/K, ABCL/1, которые предусматривают сходные механизмы параллелизма и синхронизации. Во всех этих языках можно создавать активные объекты, код которых постоянно выполняется параллельно с другими активными объектами.

Во-вторых, можно использовать библиотеку классов, реализующих какую-нибудь разновидность "легкого" параллелизма. Например, библиотека AT&T для C++ содержит классы Shed, Timer, Task и т.д. Ее реализация, естественно, зависит от платформы, хотя интерфейс достаточно хорошо переносим. При этом подходе механизмы параллельного выполнения не встраиваются в язык (и, значит, не влияют на системы без параллельности), но в то же время практически воспринимаются как встроенные.

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

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

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

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

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

• Промежуточные результаты вычислений выражений.

•Локальные переменные и объекты в блоках, а также, при вызове процедур и функций (как правило эти данные существуют на стеке).

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

• Данные, сохраняемые между сеансами выполнения программы.

• Данные, сохраняемые при переходе на другую версию программы.

• Данные, переживающие программу.

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

Для решения этой задачи могут применяться специальные технологии на подобие CORBA, Microsoft COM+, SOAP, Java RMI.

2. Объекты

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

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

Термин объект в программном обеспечении впервые был введен в языке Simula и применялся для моделирования реальности.

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

В еще более общем плане объект может быть определен как нечто, имеющее четко очерченные границы.

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

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

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

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

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

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

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

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

Этот вновь введённый тип, описывающий объекты и отсутствующий в языке С, но появившийся в языках С++, Java и C# называется классом (class). Из класса создаются переменные типа class, называемые объектами. Объект - это ограниченная сущность, характеризующаяся своим состоянием и поведением.

Объект является экземпляром класса. Класс описывает всё множество объектов определённого типа, то есть объектов с таким же состоянием и поведением.

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

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

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

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

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

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

2.1 Состояние

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

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

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

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

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

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

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

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

Конкретные напитки - это самостоятельные объекты, отличные от торгового автомата (их можно пить, а автомат нет, и совершать с ними иные действия).

Тот факт, что всякий объект имеет состояние, означает, что всякий объект занимает определенное пространство (физически или в памяти компьютера).

2.2 Поведение

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

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

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

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

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

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

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

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

2.3 Идентичность

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

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

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

Время жизни объектов.

Началом времени существования любого объекта является момент его создания (отведение участка памяти), а окончанием - возвращение отведенного участка памяти системе.

3. Классы

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

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

Класс - это некое множество объектов, имеющих общую структуру и общее поведение.

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

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

Тип class (класс) объектно-ориентированных языков программирования C++/CLI, C# и Java описывает множество однотипных объектов с одними и теми же данными и функциями, то есть обладающих общим состоянием и поведением.

Обычно большинство данных, функций и операций скрыто (рrivate) внутри класса и не доступно вне объекта и лишь только те из них, без которых невозможно управление объектом извне, открыты (рublic).

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

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

3.1 Типы отношений классов

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

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

  • ассоциация
  • наследование
  • агрегация
  • использование
  • инстанцирование
  • метакласс.

3.2 Ассоциация

Пример. Желая автоматизировать розничную торговую точку, мы обнаруживаем две абстракции - товары и продажи. На рис. 3-4 показана ассоциация, которую мы при этом усматриваем. Класс Product - это то, что мы продали в некоторой сделке, а класс Sale - сама сделка, в которой продано несколько товаров. Надо полагать, ассоциация работает в обе стороны: задавшись товаром, можно выйти на сделку, в которой он был продан, а пойдя от сделки, найти, что было продано.

В C++ это можно выразить с помощью того, что Румбах называет погребенными указателями. Вот две выдержки из объявления соответствующих классов:

class Product;

class Sale;

class Product { 
public: 
... 
protected:

Sale* lastSale;

};

class Sale { 
public: 
... 
protected:

Product** productSold;

};

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

3.3 Наследование

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

class Time...

struct ElectricalData {

Time timeStamp; 
int id; 
float fuelCell1Voltage, fuelCell2Voltage; 
float fuelCell1Amperes, fuelCell2Amperes; 
float currentPower;

};

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

Значительно лучше построить иерархию классов, в которой от общих классов с помощью наследования образуются более специализированные; например, следующим образом:

class TelemetryData { 
public:

TelemetryData(); 
virtual ~TelemetryData(); 
virtual void transmit(); 
Time currentTime() const;

protected:

int id; 
Time timeStamp;

};

В этом примере введен класс, имеющий конструктор, деструктор (который иаследники могут переопределить) и функции transmit и currentTime, видимые для всех клиентов. Защищенные элементы id и timeStamp несколько лучше инкапсулированы - они доступны только классу и его подклассам. Заметьте, что функция currentTlrne сделана открытой, благодаря чему значение timeStamp можно читать (но не изменять).

Теперь разберемся с ElectricalData:

class ElectricalData : public TelemetryData { 
public:

ElectricalData(float v1, float v2, float a1, float a2); 
virtual ~ElectricalData(); 
virtual void.transmit(); 
float currentPower() const;

protected:

float fuelCell1Voltage, fuelCell2Voltage; 
float fuelCell1Amperes, fuelCell2Amperes;

};

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

3.4 Агрегация

Пример. Отношение агрегации между классами имеет непосредственное отношение к агрегации между их экземплярами. Рассмотрим вновь класс TemperatureController:

class TemperatureController { 
public:

TemperatureController(Location); 
~TemratureController(); 
void process(const TemperatureRamp&); 
Minute schedule(const TemperatureRamp&) const;

private:

Heater h;

}; 

3.5 Использование

Пример. В недавнем примере объекты rampController и growingRamp иллюстрировали связь между объектами, которую мы представляли в виде отношения использования между их классами TemperatureController и TemperatureRamp.

class TemperatureController { 
public:

TemperatureController(Location); 
~TemperatureController(); 
void process(const TemperatureRamp&); 
Minute schedule(const TemperatureRamp&) const;

private:

Heater h;

};

Класс TemperatureRamp упомянут как часть сигнатуры функции-члена process; это дает нам основания сказать, что класс TemperatureController пользуется услугами класса TemperatureRamp.

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

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

Queue<int> intQueue; 
Queue<DisplayItem*> itemQueue;

Объекты intQueue и itemQueue - это экземпляры совершенно различных классов, которые даже не имеют общего суперкласса. Тем не менее, они получены из одного параметризованного класса Queue. По причинам, которые мы объясним позже в главе 9, во втором случае мы поместили в очередь указатели. Благодаря этому, любые объекты подклассов DisplayItem, помещенные в очередь, не будут "срезаться", но сохранят свое полиморфное поведение. 

3.6 Метаклассы

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

Заключение

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

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

Список литературы

1. Буч Г., Рамбо Дж., Джекобсон А. Классика CS. 2-е изд. – СПб.: Петербург, 2006. – 736 с.

2. Леоненков А.В. Самоучитель UML. 2-е издание переработанный и дополненный – СПб.: БХВ-Петербург, 2004. 432 с.

3. Грехем И. Объектно-ориентированные методы. Принципы и практика.

4. Медведев В.И. Особенности объектно-ориентированного программирования на C++/CLI, C# и Java. 2-е изд., испр. и доп. - Казань: РИЦ «Школа», 2010.-444 c.: ил. ISBN 978-5-4233-0007-4 р. с англ. _ М.: Вильямс, 2004. – 880 с.

5. Мухортов В.В., Рылов В.Ю. Объектно-ориентированное программирование, анализ и дизайн. Методическое пособие. Новосибирск, 2002.

6. Катаев М.Ю.Объектно-ориентированное программирование: Учебное пособие. - Томск: Томский межвузовский центр дистанционного образования, 2000. - 145 с.