10236

Объектно-ориентированное программирование. Структурный подход в программировании

Лекция

Информатика, кибернетика и программирование

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

Русский

2015-01-19

111 KB

47 чел.

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

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

   8.1. Структурный подход в программировании.

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

  Другими факторами, влияющими на эволюцию методов проектирования и создания ПП, являются:

- изменение архитектур вычислительных средств (ВС) в интересах повышения
производительности, надежности;

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

  Выделяют 5-ть источников сложности программирования:

  - решаемая задача;

  - язык программирования;

  - среда выполнения программы;

  - технологический процесс коллективной разработки и создания ПП;

  - стремление к универсальности и эффективности алгоритмов и типов данных.

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

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

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

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

  Теоретическое оформление структурный подход получил в начале 70-х годов в работах теоретиков и практиков программирования(А.П.Ершова, Э. Йодана, Н.Вирта). Следует отметить появление структурного программирования, в котором нашла определенное отражение идея упорядочивания структуры программы. Структурное программирование ориентирует на составление программ, структура которых близка к «дереву» операторов или блоков. Использование структуры типа «дерево» в качестве своеобразного эталона объясняется тем, что это простая для анализа и реализации структура.

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

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

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

  Развитие языков в направлении повышения эффективности составления прикладных программ привело к разделению языков по следующим уровням:

  - низкий уровень (машинно-ориентированные языки - языки ассемблера),

  - высокий уровень (процедурно-ориентированные языки: FORTRAN, ALGOL,    

  PL/1, Pascal),

  - уровень решаемой задачи (проблемно-ориентированные языки - SQL).

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

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

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

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

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

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

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

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

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

  Объектный подход начал развиваться в программировании с 70-х годов (Smalltalk, CLOS, Ada). Эти языки называются объектными. Иерархическая классификация объектов и наследование свойств являются отправными идеями появившегося в 80-х годах объектно-ориентированного подхода. Одной из причин сравнительно медленного становления объектно-ориентированного стиля программирования является его существенное отличие от процедурно-ориентированного стиля.

   8.2. Концепции объектно-ориентированного программирования.

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

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

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

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

   - наследования;

    - полиморфизма.

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

   Объекты и классы.

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

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

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

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

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

    Инкапсуляция свойств объектов.

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

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

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

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

Можно сказать,  что инкапсуляция подразумевает под собой скрытие данных (data hiding),  что позволяет защитить эти данные.

А теперь определение,  которое точно определяет суть инкапсуляции:

Переменные состояния объекта скрыты от внешнего мира. Изменение состояния объекта(его переменных) возможно ТОЛЬКО с помощью его методов(операций).

Почему же  это так важно? Этот принцип позволяет защитить переменные состояния объекта от неправильного их использования.

Это  существенно  ограничивает  возможность  введения  объекта  в  недопустимое  состояние и несанкционированное разрушение этого объекта.

Для иллюстрации приведенного выше постулата рассмотрим пример.

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

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

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

  Для расширения доступа к элементам данных, имеющим атрибуты private или protected, в классе можно реализовать с атрибутом public специальные методы доступа к собственным и защищенным элементам данных.

  Методы в классе могут быть объявлены как дружественные (friend) или виртуальные (virtual). Иногда встречается объявление перегружаемых (overload)  функций.  

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

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

    Наследование свойств.

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

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

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

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

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

  Наследование в ООП позволяет адекватно отражать родственные отношения объектов предметной области. Если класс В обладает всеми свойствами класса А и еще имеет дополнительные свойства, то класс А называется базовым (родительским), а класс В называется наследником класса А. В C++ возможно одиночное (с одним родителем) и множественное (с несколькими родителями) наследование.

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

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

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

  Примеры родственных классов: Координаты на экране -> Цветная точка -> Прямая -> Прямоугольник. Здесь направление стрелки указывает порядок наследования свойств классов.

  При указании базового (родительского) класса в описании класса в С++  требуется указать ключевое слово public.  Указание этого ключевого слова позволит получить свободный доступ ко всем методам класса,  как если бы они были описаны в самом производном классе. В противном же случае, мы не сможем получить доступ к методам родительского класса.

  Пример описания наследования классов на С++:

class A

{

. . . . .

}

class B : public A

{

. . . . .

}  

   Полиморфизм поведенческих свойств объектов.

  Слово  полиморфизм  имеет  греческое  происхождение  и  переводится  как  "имеющий  много форм".

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

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

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

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

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

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

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

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

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

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

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

     Создание и уничтожение объектов.

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

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

   Взаимодействие объектов и сообщения.

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

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

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

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

   8.3. Этапы объектно-ориентированного программирования.

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

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

  1.  Определение основных понятий предметной области и соответствующих им классов, имеющих определенные свойства (возможные состояния и действия). Обоснование вариантов создания объектов.
  2.  Определение или формулирование принципов взаимодействия классов и взаимодействия объектов в рамках программной системы.
  3.  Установление иерархии взаимосвязи свойств родственных классов.
  4.  Реализация иерархии классов с помощью механизмов инкапсуляции, наследования и полиморфизма.
  5.  Для каждого класса реализация полного набора методов для управления свойствами объектов.

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

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

  ООП обладает следующими достоинствами:

- использование более естественных понятий и имен из повседневной жизни или предметной области;

- простота введения новых понятий на основе старых;

- отображение в библиотеке классов наиболее общих свойств и отношений между объектами моделируемой предметной области;

- естественность отображения пространства решаемой задачи в пространство объектов программы;

- простота внесения изменений в классы, объекты и программу в целом;

- полиморфизм классов упрощает составление и понимание программ;

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

- передача параметров в конструкторах объектов повышает гибкость создаваемых программных систем.


  В качестве недостатков ООП можно отметить следующие:

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

- большие затраты времени на разработку библиотеки классов, поэтому ООП це-лесообразно при создании больших программ, а не при написании маленьких единичных программ;

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

  Целесообразность применения технологии ООП для создания конкретной программной системы определяется двумя главными факторами:

  - спецификой предметной области и решаемой прикладной задачи;

  - особенностями используемого языка программирования (транслятора).

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

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


 

А также другие работы, которые могут Вас заинтересовать

51207. Разработка контекстного анализатора 48.83 KB
  Для предложенного преподавателем варианта контекстного условия расширить атрибутную грамматику из лабораторной работы № 4 добавлением атрибутов, правил их вычисления, правил вычисления контекстных условий. Включить в программу синтаксического анализатора из лабораторной работы № 4 действия по вычислению атрибутов и проверки контекстных условий.
51210. Побудова багаточлена Лагранжа. Складання програми 41.21 KB
  Мета. Навчитися будувати багаточлен Лагранжа, скласти програму. Обладнання. Лист формату А4, ручка, ПК, програмне забезпечення С++. Хід роботи Правила ТБ Теоретичні відомості Індивідуальне завдання
51211. Сетевое планирование производственных процессов 156 KB
  Цель работы Изучение сетевого планирования процессов на основе построения и расчета сетевого графа. Постановка задачи Построить сетевой граф процесса, 10-15 работ. Провести расчет графа и анализ планируемого процесса. Разработать программу реализации.
51212. Анализ организационных структур АСУ 146.93 KB
  Постановка задачи Вычислить время пребывания заявки в сети изображенной на рисунке. Матрица вероятностей Р для этой сети имеет вид P = = m = Основные теоретические сведения 1. Стохастическая сеть состоит из конечного числа элементов i = 012n внешний источник среда откуда в сеть поступают заявки и куда они направляются из сети принимается за нулевой элемент i = 0. Для отображения связей между элементами стохастической сети применяется направленный граф передач вершины S0S1Sn которого соответствуют одноименным элементам а...
51215. Настройка BIOS 20.46 KB
  При включении компьютера многочисленные и разнообразные процессы происходят еще до того, как начинает загружаться операционная система. Нам эти процессы незаметны, но их результат налицо — компьютер начинает работать. Первой из систем включается BIOS (Basic Input Output System — начальная, или основная система ввода/вывода).