Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

OOP / Лекция 2

.pdf
Скачиваний:
39
Добавлен:
20.04.2015
Размер:
81.4 Кб
Скачать

Лекция 2

1.Обзор стилей программирования

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

1.1. Процедурное программирование

Процедурное

(императивное)

программирование

является

отражением

архитектуры традиционных ЭВМ, предложенной фон Нейманом в

40-х годах.

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

многим пример неимперативного программирования - электронная таблица. В

ней

значения ячеек задаются выражениями, а не командами, определяющими,

как

вычислять это значение. Нигде также не задается порядок вычисления значений ячеек, гарантируется, что вычисления будут выполнены в правильном порядке с учетом зависимости ячеек друг от друга. В электронной таблице не используется присваивание, то есть указание изменить текущее значение ячейки. Если мы не управляем сами последовательностью вычислений, то мы и не знаем, когда произойдет присваивание, а поэтому от него мало пользы. К процедурным языкам относятся Basic, Cobol, Fortran, Pascal, C и Ada.

1.2. Структурное программирование

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

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

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

логика алгоритма и программы должна допускать только три основные

структуры

- последовательное выполнение, ветвление

и повторение.

Недопустим оператор передачи управления в любую точку программы;

при

разработке документация должна создаваться

одновременно с

программированием, в виде комментариев к программе.

Цель структурного программирования - повышение надежности программ, обеспечение сопровождения и модификации, облегчение и ускорение разработки. Идеи структурного программирования появились в начале 70-годов в компании IBM, в их разработке участвовали такие известные ученые как Э. Дейкстра, Х. Милс, Э. Кнут, С. Хоор.

1.3. Функциональное программирование

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

представляют собой вызовы других функций и предложений, управляющих последовательностью вызовов. Вычисления начинаются с вызова некоторой функции, которая в свою очередь вызывает функции, входящие в ее определение и т. д. в соответствии с иерархией определений и структурой условных предложений. Функции часто либо прямо, либо опосредованно вызывают сами себя. Каждый вызов возвращает некоторое значение в вызвавшую его функцию, вычисление которой после этого продолжается; этот процесс повторяется до тех пор, пока запустившая вычисления функция не вернет конечный результат пользователю. "Чистое" функциональное программирование не признает присваиваний и передач управления. Разветвление вычислений основано на механизме обработки аргументов условного предложения. Повторные вычисления осуществляются через рекурсию, являющуюся основным средством функционального программирования. Первый функциональный язык программирования (Лисп) был разработан американским ученым Дж. Маккарти (J. McCarthy) в 1958-1961 гг. на основе алгебры списочных структур, лямбдаисчисления и теории рекурсивных функций. К настоящему времени созданы такие функциональные языки программирования как Scheme, Рефал, Haskell, Sisal.

1.4. Логическое программирование

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

логическом программировании разрешена конструкция типа "Определить

фирму,

имеющую самую высокую в городе среднюю зарплату сотрудников",

которой

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

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

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

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

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

2. Основные принципы объектно-ориентированного программирования

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

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

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

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

полиморфизм

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

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

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

отладку программного кода после изменений.

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

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

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

Наследование состоит в процессе создания новых объектов (потомков) на основе уже имеющихся объектов (предков) с передачей их свойств и методов по наследству. Наследование позволяет модифицировать поведение объектов и придает объектно-ориентированному программированию исключительную гибкость. Идея наследования заимствована у природы, где потомство, наследуя основные характеристики предков, обладает некоторыми оригинальными отличительными особенностями. Программный объект также может унаследовать от объекта-предка некоторые свойства и методы, а добавленные к этим унаследованным атрибутам собственные свойства и методы позволяют расширить функциональность по отношению к объекту-предку. Преимущество принципа наследования заключается в повторном использовании кода, когда каждый новый объект не создается с нуля, а строится на фундаменте уже существующего объекта. При этом уменьшается как размер кода, так и сложность программы. Благодаря использованию принципа наследования в современные системы программирования включены библиотеки классов, которые представляют собой многоуровневые иерархические системы классов, описывающих элементы программного или пользовательского интерфейса прикладной программы. В основе подобных систем лежат базовые классы, которые обычно очень просты и являются обобщением свойств всех остальных классов библиотеки. Классы-потомки базовых дополняются собственными свойствами, приобретая дополнительную функциональность. Они, в свою очередь, становятся основой для классов следующих уровней иерархии. Таким образом формируется гибкая и стройная система классов. Примерами библиотек классов, построенных по такому принципу, можно назвать Turbo Vision, Objects Windows Library или Visual Component Libraries фирмы Inprise (Borland) или Microsoft Foundation Classes фирмы Microsoft.

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

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

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

Соседние файлы в папке OOP