Уникальная идентичность объектов. Идентичность объектов Вселенной. Идентичность объектов в реляционных и объектно-ориентированных моделях. Примеры.



Хошафян и Коуплэнд предложили следующее определение идентичности: "Идентичность - это такое свойство объекта, которое отличает его от всех других объектов".

При рассмотрении объектов вселенной можно сказать, что их идентичность гарантируется разным состоянием (например, два объекта не могут иметь одни координаты). В реляционных моделях идентичность также достигается различным состоянием (понятие первичного ключа). В большинстве же языков программирования для различения временных объектов их именуют или назначают UID, тем самым путая адресуемость (т.е. физическое размещение объектов в памяти) и идентичность". Источником множества ошибок в объектно-ориентированном программировании является неумение отличать имя объекта от самого объекта. Объявим экземпляры определенного класса DisplayItem: DisplayItem item1; DisplayItem* item2 = new DisplayItem(Point(75, 75)); DisplayItem* item3 = new DisplayItem(Point(100, 100)); DisplayItem* item4 = 0; При выполнении этих операторов возникают четыре имени и три разных объекта. Конкретно, в памяти будут отведены четыре места под имена item1, item2, item3, item4. При этом item1 будет именем объекта класса DisplayItem, а три других будут указателями. Кроме того, лишь item2 и item3 будут на самом деле указывать на объекты класса DisplayItem. У объектов, на которые указывают item2 и item3, к тому же нет имен, хотя на них можно ссылаться "разыменовывая" соответствующие указатели: например, *item2. Поэтому мы можем сказать, что item2 указывает на отдельный объект класса DisplayItem, на имя которого мы можем косвенно ссылаться через *item2. Уникальная идентичность (но не обязательно имя) каждого объекта сохраняется на все время его существования, даже если его внутреннее состояние изменилось. Эта ситуация напоминает парадокс Зенона о реке: может ли река быть той же самый, если в ней каждый день течет разная вода?

Рассмотрим результат выполнения следующих операторов: item1.move(item2->location()); item4 = item3; item4->move(Point(38, 100));

Хотя объект item1 и объект, на который указывает item2, имеют одинаковое состояние, они остаются разными объектами. Кроме того, мы изменили состояние объекта *item3, использовав его новое косвенное имя item4. Эта ситуация, которую мы называем структурной зависимостью, подразумевая под этим ситуацию, когда объект именуется более чем одним способом несколькими синонимичными именами. Структурная зависимость порождает в объектно-ориентированном программировании много проблем. Трудность распознания побочных эффектов при действиях с синонимичными объектами часто приводит к "утечкам памяти", неправильному доступу к памяти, и, хуже того, непрогнозируемому изменению состояния. Например, если мы уничтожим объект через указатель item3, то значение указателя item4 окажется бессмысленным; эта ситуация называется повисшей ссылкой. Выполним следующее действие: item2 = &item1; При этом произошла утечка памяти, - объект, на который первоначально указывала ссылка item2, никак не именуется ни прямо, ни косвенно, и его идентичность потеряна. В Smalltalk и C# память, отведенная под объекты, будет вновь возвращена системе сборщиком мусора. В языках типа C++ такая память не освобождается, пока не завершится программа, создавшая объект.

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

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

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

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

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

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

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

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

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

7. Фундамент объектно-ориентированных методов. Абстрагирование. Пример на С++.

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

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

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

8. Фундамент объектно-ориентированных методов. Инкапсуляция. Пример на С++.

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

class Cat

{

private:

    TColor CatColor;

    void Purr() {DoPurr();}

protected: virtual void DoPurr ();

public: void Caress() { Purr(); }

};

10. Фундамент объектно-ориентированных методов. Иерархия. Виды иерархий. Пример на С++.

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

Виды иерархий: Одиночное наследование («is-a»), Множественное наследование («is-a»), Агрегация («part of»).

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

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

Принципы абстрагирования, инкапсуляции и иерархии находятся между собой в некоем здоровом конфликте. Данфорт и Томлинсон утверждают: "Абстрагирование данных создает непрозрачный барьер, скрывающий состояние и функции объекта, а принцип наследования требует открыть доступ и к состоянию, и к функциям объекта для производных объектов". Различные языки программирования по-разному находят компромисс между наследованием и инкапсуляцией; наиболее гибким в этом отношении является C++ (блоки класса private, public и protected).

Если иерархия "is а" определяет отношение "обобщение/специализация", то отношение "part of" (часть) вводит иерархию агрегации. Например, огород включает растения и содержитит алгоритмы их совместного выращивания. Это - абстракция огорода, состоящая из массива растений и плана выращивания.

Имея дело с такими иерархиями, мы часто говорим об уровнях абстракции «владение/подчинение», которые впервые предложил Дейкстра [67]. В иерархии классов “is-a” является обобщением, а нижестоящая - специализацией. В иерархии "part of" класс владеющий объектами находится на более высоком уровне абстракции, чем любой из использовавшихся при его реализации. Так класс Garden стоит на более высоком уровне, чем класс Plant. В объектно-ориентированном программировании агрегация обретает новую мощь: агрегация позволяет физически сгруппировать логически связанные структуры.

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

12. Фундамент объектно-ориентированных методов. Типизация. Языки со сильной и слабой типизацией. Типизация в C++.

Понятие типа взято из теории абстрактных типов данных. Дойч определяет тип, как "точную характеристику свойств, включая структуру и поведение, относящуюся к некоторой совокупности объектов". В ООП достаточно считать, что термины тип и класс взаимозаменяемы (однако в некторых языках их различали -  Trellis/Owl, Smalltalk). В частности: Типизация - это способ защититься от использования объектов одного класса вместо другого, или по крайней мере управлять таким использованием.Типизация заставляет нас выражать наши абстракции так, чтобы язык программирования, используемый в реализации, поддерживал соблюдение принятых проектных решений.

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

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

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

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

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

Типизация и связывание - разные вещи. Типизация следит за соответствием типов, а связывание определяет время, когда имена связываются с типами. Статическое связывание (раннее связывание) означает, что типы всех переменных и выражений известны во время компиляции; динамическое связывание (позднее связывание) означает, что типы неизвестны до момента выполнения программы. Концепции типизации и связывания являются независимыми, поэтому в языке программирования может быть: типизация - сильная, связывание - статическое (Ada), типизация - сильная, связывание - динамическое (C++, Object Pascal), или и типов нет, и связывание динамическое (Smalltalk, VBA), раннее связывание и слабая типизация (CLOS).

 14. Фундамент объектно-ориентированных методов. Параллелизм. Поддержка параллелизма в языках программирования. Параллелизм в C++.

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

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

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

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

Во-первых, параллелизм - это внутреннее свойство некоторых языков программирования. Так, для языка Ada механизм параллельных процессов реализуется как задача. В Smalltalk есть класс process, которому наследуют все активные объекты. Есть много других языков со встроенными механизмами для параллельного выполнения и синхронизации процессов - Actors, Orient 84/K, ABCL/1 и т.д. Во-вторых, можно использовать библиотеку классов, реализующих какую-нибудь разновидность "легкого" параллелизма (при котором различные процессы имеют общее адресное пространство). Например, библиотека PThreads для C++. Ее реализация, естественно, зависит от платформы, хотя интерфейс достаточно хорошо переносим. При этом подходе механизмы параллельного выполнения не встраиваются в язык, но в то же время практически воспринимаются как встроенные. Наконец, в-третьих, можно создать иллюзию многозадачности с помощью прерываний. Для этого надо кое-что знать об аппаратуре.

15. Фундамент объектно-ориентированных методов. Сохраняемость. Поддержка сохраняемости в языках. Сохраняемость в С++.

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

Языки программирования, как правило, не поддерживают понятия сохраняемости; примечательным исключением является Smalltalk, в котором есть протоколы для сохранения объектов на диске и загрузки с диска. Однако, записывать объекты в неструктурированные файлы - это все-таки наивный подход, пригодный только для небольших систем. Как правило, сохраняемость достигается применением коммерческих ООБД. Другой вариант - создать объектно-ориентированную оболочку для реляционных СУБД.

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

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


Дата добавления: 2018-04-15; просмотров: 911; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!