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

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

1. Трассировка

2. Контрактное программирование, в частности проверка пред и пост условий

3. Обработка ошибок.

4. Реализация систем безопасности.

Динамические языки

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

Больше подходят для быстрой разработки приложений.

Phyton,PHP,Rudy,Javascript.

Операция склеивания строк – конкатенация.

[Объектно-ориентированные языки программирования ]

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

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

Наследование – Создание нового класса объектов путем добавления новых элементов (методов).

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

Типизация – позволяет устранить ошибки на момент компиляции.

Объекты, классы и методы могут быть полиморфными данными, следовательно гибкость и универсальность.

Сложность адекватной формализации объектной теории, следовательно трудность тестирования и верификации ПО.

С++, Ada, pascal, PHP.

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

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

Язык описания интерфейсов

Похож на описание классов С++.

Язык спецификаций.

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

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

Программа – совокупность логических правил при высказывании.

Используется в экспертных системах и системах принятия решений.

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

Prolog,Oz,Frill.

Специфичность решаемых задач.



Нелинейность структуры программы.

Сложность эффективной реализации в системе реального времени.

Параллельное программирование

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

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

Часто применяют в системах реального времени.

Недостаток – высокие накладные расходы на разработку программ.

Язык сценариев (скриптовые)

Программа состоит из сценариев, последовательностей операций.

Скриптовые языки или языки сценариев пакетной обработки.

8. Унификация и хорновский клоз в логических языках программирования .

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

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

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



Унификация - При поиске решений для множеств ограничений мы используем идею, высказанную Хиндли (Hindley, 1969) и Милнером (Milner, 1978), кото- рая состоит в использовании унификации (unification) (Robinson, 1971) для проверки непустоты множества решений и, если это так, нахожде- ния «наилучшего» из его элементов в том смысле, что все остальные решения могут быть непосредственно получены из него.

Дизъюнкт Хорна (хорновский дизъюнкт, клоз Хорна) - дизъюнкция, в которой содержится не более одного положительного литерала.

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

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

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

Пролог пытается отождествить термы при доказательстве, или согласовании, целевого утверждения. Например, в программе для согласования запроса?- человек(Х) целевое утверждение человек(X) может быть отождествлено с фактом служащий(Иван), в результате чего переменная Х станет конкретизированной: Х= Иван.

Хорновский клоз (Ноrn clause) - это формула, в которой с помощью конъюнкции («и») элементарных формул выводится одиночная элементарная формула:

(s=>t)<=(t = tl||t2)^(s=>tl)

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

Чтобы инициализировать вычисление логической программы, задается цель:

“wor” => "Hello world"?

Машина вывода пытается сопоставить цель и вывод формулы. В данном случае соответствие устанавливается сразу же: "wor" соответствует переменной s, a "Hello world" - переменной t. Это определяет подстановку выражений (в данном случае констант) для переменных; подстановка применяется ко всем переменным в формуле:

"wor" => "Hello world" <= ("Hello world" = tl || t2) ^ ("wor" => tl)

Теперь мы должны показать, что:

("Hello world" = t1|| t2) ^ ("wor" => tl)

является истинным, и это ведет к новому соответствию образцов, а именно попытке установить соответствие "Hello world" с tl || t2. Здесь, конечно, может быть много соответствий, что приведет к поиску. Например, машина вывода может допускать, чтобы tl указывало на "Не", a t2 указывало на "llо world"; эти подстановки затем проводятся во всем вычислении.

9. Модель вычислений функциональных языков программирования .

10. Языки программирования низкого уровня .

Язык программирования низкого уровня - язык программирования, близкий к программированию непосредственно в машинных кодах используемого реального или виртуального (например, Java, Microsoft .NET) процессора. Для обозначения машинных команд обычно применяется мнемоническое обозначение. Это позволяет запоминать команды не в виде последовательности двоичных нулей и единиц, а в виде осмысленных сокращений слов человеческого языка (обычно английских).

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

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

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

Намечают три вида низкоуровневых языков

1 Машинный код

2 Мнемо код

3 Ассемблер, макроассемблер

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

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

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

Макроассемблеры является расширением ассемблера за счет включения макросредств.

11. Средства разработки графического интерфейса пользователя. Эргономические свойства человеко-машинного интерфейса .

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

Эргономичность - интегральный показатель степени выполнения эргономических требований;

Показатели качества деятельности оператора (время решения задачи, производительность, число ошибок, состояние здоровья и т.д.);

Надёжность деятельности оператора (своевременное и безошибочное выполнение функций);

Эффективность СЧМ;

Напряжённость и экстремальность деятельности и т.д.

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

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

Человеко-машинный интерфейс условно можно разделить на 3 подгруппы:

текстовый (командные строки) интерфейс;

смешанный (псевдографический) интерфейс

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

графический интерфейс

(это система средств для взаимодействия пользователя с компьютером, основанная на представлении всех доступных пользователю системных объектов и функций в виде графических компонентов экрана (окон, значков, меню, кнопок, списков и т.п.) К этому виду интерфейсов относятся такие системы как, Mac OS, Solaris, GNU/Linux, Microsoft Windows, NeXTSTEP

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

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

К процедурным языкам относятся Basic, Cobol, Fortran, Pascal, C и Ada.

Преимущества:

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

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

Модули можно отлаживать и тестировать независимо от всей программы.

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

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

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

Примеры: паскаль, С, Бейсик, Ада, Фортран.

13. Обоснование выбора языка программирования .

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

Язык программирования служит двум связанным между собой целям: он дает программисту аппарат для задания действий, которые должны быть выполнены, и формирует концепции, которыми пользуется программист, размышляя о том, что делать. Первой цели идеально отвечает язык, который настолько «близок к машине», что всеми основными машинными аспектами можно легко и просто оперировать достаточно очевидным для программиста образом. С таким умыслом первоначально задумывался C. Второй цели идеально отвечает язык, который настолько «близок к решаемой задаче», чтобы концепции её решения можно было выражать прямо и коротко. С таким умыслом предварительно задумывались средства, добавленные к C для создания С++.

Главным образом выбор языка программирования зависит от

1. Решаемой задачи

2. Операционной системы

3. Возможностей языка программирования

4. Цена программного обеспечения

5. Обучение

6. Сопровождение

7.Удобство

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

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

Недостатки:

Язык компилируется в момент исполнения кода. Каждый раз, когда вы открываете сайт, javascript код начинает компилироваться. Как минимум увеличивается время выполнения программы.

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

Не привычная для многих программистов объектная модель. Классы и наследование классов присутствует, но оно сильно отличается от привычной многим реализаций в языках программирования C++/C#/Java.

Достоинства:

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

Популярность JavaScript открывает перед программистом немалое количество готовых библиотек, которые позволяют значительно упростить написание кода и нивелировать несовершенства синтаксиса;

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

14. Перегрузка в языках программирования .

Перегрузка процедур и функций - возможность использования одноимённых подпрограмм: процедур или функций в языках программирования.

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

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

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

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

Перегружать операции имеет смысл только в том случае, если вновь вводимые операции аналогичны предопределенным.

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

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

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

Int add_values(int a, int b)

{ return(a + b);}

Int add_values(int a, int b, int c)

{ return(a + b+c);}

Int add_values(float a, float b)

{ return(a + b);}

{cout<<”200+800=”<< add_values (200,800);

cout<<”100+200+800=”<< add_values (100,200,800);

cout<<”0.5+0.2=”<< add_values (0.5,0.2);}

Механизм реализации в языке :

Улучшает удобочитаемость программ/

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

Варианты решения:

1. Требовать однозначный проходящий вариант перегруженной функции.

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

Приоритет и ассоциативность – порядок выполнения и следование операторов.

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

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

Пример: операция a+b все нормально для чисел, но для строк важен порядок, т.к. это конкатенация и a+b!=b+a

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

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

Преимущества

1) Высокий уровень машинной независимости

2) Возможность откатов (возвращение к предыдущей подцели, и отрицательного в результате анализа одного из вариантов в процессе поиска решения)

Недостатки

1) Специфичность класса решаемых задач.

2) Сложность эффективной реализации для принятия решения в реальном времени.

3) Нелинейность структуры программы.

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

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

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

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

· Задача программиста – описание логической модели предметной области в терминах объектов, их свойств и отношений между ними (без деталей): описание данных и логики их обработки ~ аналогия с ООП.

· Удобство описания отношений между объектами (реляционная модель).

· Компактность кода (обработка структурированных данных, лог. правила).

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

· Легкость понимания (описание отд. правил), отладки программ (trace).

· Легкость описания сложных структур данных (деревья, списки и т.п.).

· Эффективный метод вычислений – рекурсия.

· Отсутствие указателей, операторов присваивания и безусловного перехода.

· Множество областей для применения: автоматический перевод, обработка текстов, экспертные системы, САПР, Data-minig системы, автоматическое управление, СУБД, символьные вычисления.

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

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

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

Преимущества

1) Концептуальная близость к предметной области. Произвольные структуры и назначения.

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

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

4) Объекты классы и методы могут быть полиморфными, что делает программное обеспечение более гибким и универсальным.

Недостаток

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

<Объектно-ориентированное программирование (ООП)>

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

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

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

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

Связь: OOA→OOP→OOD

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

ОО ЯП

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

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

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

3) Типы (классы) могут наследовать атрибуты супер типов (суперклассов).

Преимущества объектной модели:

Позволяет использовать возможности ОО языка программирования.

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

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

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

Ориентирована на человеческое восприятие мира.

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

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

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

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

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

Недостатки:

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

17. Полиморфизм в объектно-ориентированном программировании. Виртуальные функции. Таблицы виртуальных функций .

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

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

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

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

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

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

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

Виртуальные функции - применяются для реализации динамического полиморфизма

Чистая виртуальная функция – это функция-член, которая объявлена со спецификатором = 0 вместо тела:

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

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

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

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

Механизм работы virtual

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

Количество элементов в массиве равно количеству виртуальных функций в массиве.

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

Помимо создания таблицы виртуальных функций, в базовом классе объявляется поле __vfptr – указатель на vtable. Этот указатель наследуется всеми производными классами. __vfptr указывает на vtable класса, которому принадлежит объект.

Если процессор видит, что метод виртуальный, то ищет в таблице нужную запись. Адрес таблицы он узнает через __vfptr.

Абстрактный класс

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

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

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

Виртуальный деструктор

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

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

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

Полиморфи́зм (от греч. πολὺ- - много, и μορφή - форма) в языках программирования - возможность объектов с одинаковой спецификацией иметь различную реализацию.

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

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

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

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

1) Преобразование типов

2) Перегрузка

3) Родовой настраиваемый сегмент – параметризованный шаблон подпрограммы, использующийся для создания различных конкретных экземпляров подпрограммы. ]Динамический полиморфизм – структурная неопределенность остается до этапа выполнения.

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

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

Таблица виртуальных функций – это одномерный массив указателей на функции. Количество элементов в массиве равно количеству виртуальных функций в классе.

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

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

18. Структура языка программирования. Синтаксис и семантика языков программирования. Расширенная форма Бэкуса-Наура .

{Основные элементы языка программиро

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

Проектируемый сайт будет выполнен на языке разметки гипертекста HTML с применением каскадных таблиц стилей CSS, серверного языка программирования PHP и языка программирования JavaScript.

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

Проектируемый web-ресурс будет выполнен преимущественно на языках программирования PHP и JavaScript. PHP (англ. PHP: Hypertext Preprocessor - «PHP: препроцессор гипертекста»; первоначально Personal Home Page Tools - «Инструменты для создания персональных веб-страниц») - скриптовый языкпрограммирования общего назначения, интенсивно применяемый для разработки веб-приложений. В настоящее время поддерживается подавляющим большинством хостинг-провайдеров и является одним из лидеров среди языков программирования, применяющихся для создания динамических веб-сайтов. Основное преимущество PHP-скрипов это то, что они выполняются на стороне сервера и их невозможно увидеть в окне браузера или исходном коде страницы.

1.3 Выбор языка программирования

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

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

Серверные языки. Когда пользователь дает запрос на какую-либо страницу (переходит на неё по ссылке или вводит адрес в адресной строке своего браузера), то вызванная страница сначала обрабатывается на сервере, то есть выполняются все программы, связанные со страницей, и только потом возвращается к посетителю по сети в виде файла. Этот файл может иметь расширения: HTML, PHP, ASP, Perl, SSI, XML, DHTML, XHTML.

Работа программ уже полностью зависима от сервера, на котором расположен сайт, и от того, какая версия того или иного языка поддерживается. Список серверных языков программирования: PHP, Perl, Python, Ruby, Любой.NET язык программирования (технология ASP.NET), Java, Groovy.

Наиболее популярные языки веб-программирования представлены на рисунке 1.1

Рисунок 1.1 Наиболее популярные языки веб-программирования

PHP (Profeshional Hypertext Preprocessor)

Язык исполняемый на стороне веб-сервера, написанный на языке C++, поэтому содержит много общего. История PHP начинается с человека по имени Rasmus Lerdorf в 1995 году, когда он создаёт простую программу на Perl, которая представляет собой скрипт по подсчёту посещения его резюме. Завоевав большую популярность скрипт требовал своей доработки и тогда появляется первая версия PHP, написанная на С – PHP/FI (Personal Home Page / Forms Interpreter), это как бы модификация Perl для работы с формами. PHP/FI просуществовал до версии 2.0 (выпуск – 1997 г.). После этого на горизонте появились два студента Израильского университета: Andi Gutmans и Zeev Suraski, они начали детально изучать исходники (sources) языка PHP/FI и сочли его непригодным для создания больших проектов. Тогда они создали первую официальную (современную) версию PHP – PHP 3.0, вот он потомок PHP/FI. Тогда и появилось новое название PHP: Hypertext Preprocessor. Шёл 1998 год. Впоследствии появились новые задачи, с которыми 3.0 версия PHP не справлялась (достаточно посмотреть на количество новых функций, которые появились в PHP 4.0, без которых не представляется сегодня возможность эффективно работать с веб-приложениями). Разработчики начали усердно работать над ядром (kernel) PHP и вскоре появляется первая стабильная версия PHP – PHP 4.0 (сенсационная находка для веб-программистов, полностью переделанное ядро).

Perl (Practical Extraction and Report Language)

Язык Perl смело можно считать предком PHP. Действительно, при первом изучении языка в глаза бросается резкое сходство с PHP. Но это только в начале, т.к. разработчиков Perl не особо заботил вопрос об упрощении языка. В начале Perl разрабатывался для ОС семейства *nix. Отцом Perl считается Larry Wall, а разработал он язык, вначале как систему для отчётов в Unix в Usenet-конференциях в 1986 году. Пользователям понравилось, пользователи захотели больше возможностей, которыми Perl в то, время не обладал. Основная задача Perl – облегчение команд для shell, но т.к. мы обсуждаем создание веб-станиц, то мы будем говорить о применение Perl для создания веб-страниц. Вопрос же о том, какой язык выбрать: Perl или PHP настолько философский, как, к примеру, вопрос о возникновении человека на земле. Поэтому это сугубо индивидуально. Мне, например, нравятся оба языка, т.к. они по своему своеобразны, интересны, можно привести множество примеров но это уже выходит за рамки этой статьи.

Казалось бы мы рассмотрели все языки, с помощью которых можно создавать корпоративные и интерактивные веб-приложения, но стоит ещё отметить два интересных языка/систем для создания веб-страниц.

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

ASP (Active Server Pages)

Технология от Microsoft, позволяющая легко разрабатывать приложения для World Wide Web. ASP работает на платформе операционных систем линии Windows NT и на веб-сервере IIS. ASP не является языком программирования - это лишь технология предварительной обработки, позволяющая подключать программные модули во время процесса формирования Web-страницы. Относительная популярность ASP основана на простоте используемых языков сценариев (VBScript или JScript) и возможности использования внешних COM-компонент.

Технология ASP получила своё развитие в виде ASP.NET - новой технологии создания веб-приложений, основанной на платформе Microsoft .NET.

Интерпретируемый язык высокого уровня для быстрого и удобного объектно-ориентированного программирования. Язык обладает независимой от операционной системы реализацией многопоточности, строгой динамической типизацией, «сборщиком мусора» и многими другими возможностями. Руби близок по особенностям синтаксиса к языкам Перл и Эйфель, по объектно-ориентированному подходу к Smalltalk. Также некоторые черты языка взяты из Python, Лисп, Dylan и CLU.

Кроссплатформенная реализация интерпретатора языка является полностью свободной, распространяется с открытыми исходными текстами, возможностью копирования и модификации. Последней является версия 1.8.5, вышедшая 28 августа 2006.

Ruby on Rails - объектно-ориентированный программный каркас для создания веб-приложений, написанный на языке программирования Ruby. Ruby on Rails предоставляет каркас модель-представление-контроллер (Model-View-Controller) для веб-приложений, а также обеспечивает их интеграцию с веб-сервером и сервером базы данных.

Ruby on Rails является открытым программным обеспечением и распространяется под лицензией MIT.

Java - объектно-ориентированный язык программирования, разрабатываемый компанией Sun Microsystems с 1991 года и официально выпущенный 23 мая 1995 года. Изначально новый язык программирования назывался Oak (James Gosling) и разрабатывался для бытовой электроники, но впоследствии был переименован в Java и стал использоваться для написания апплетов, приложений и серверного программного обеспечения.

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

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

Часто к недостаткам этого подхода относят то, что исполнение байт-кода виртуальной машиной может снижать производительность программ и алгоритмов, реализованных на языке Java. Данное утверждение справедливо для первых версий виртуальной машины Java, однако в последнее время оно практически потеряло актуальность. Этому способствовал ряд усовершенствований: применение технологии JITs (Just-In-Time compiler), позволяющей переводить байт-код в машинный код во время исполнения программы с возможностью сохранения версий класса в машинном коде, широкое использование native-кода в стандартных библиотеках, а также аппаратные средства, обеспечивающие ускоренную обработку байт-кода (например, технология Jazelle, поддерживаемая некоторыми процессорами фирмы ARM).

Внутри Java существуют 3 основных семейства технологий:

J2EE - Java Enterprise Editon, для создания программного обеспечения уровня предприятия;

J2SE - Java Standard Editon, для создания пользовательских приложений, в первую очередь - для настольных систем;

J2ME - Java Micro Edition, для использования в устройствах, ограниченных по вычислительной мощности, в том числе мобильных телефонах, PDA, встроенных системах

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

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

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

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

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

Объектно-ориентированное программирование основано на следующих принципах:

  • - абстрагирования данных;
  • - инкапсуляции;
  • - наследования;
  • - полиморфизма;
  • - «позднего связывания».

Абстрагирование является одним из основных методов, используемых для решения сложных задач. Хоар считает, что «абстрагирование проявляется в нахождении сходств между определенными объектами, ситуациями или процессами реального мира, и в принятии решений на основе этих сходств, отвлекаясь на время от имеющихся различий» . Шоу определила это понятие так: «Упрощенное описание или изложение системы, при котором одни свойства и детали выделяются, а другие опускаются. Хорошей является такая абстракция, которая подчеркивает детали, существенные для рассмотрения и использования, и отпускает те, которые на данный момент несущественны» . Берзинс, Грей и Науман рекомендовали, чтобы «идея квалифицировалась как абстракция только, если она может быть изложена, понята и проанализирована независимо от механизма, который будет в дальнейшем принят для ее реализации» . Суммирую эти разные точки зрения, получается следующее определение абстракции: Абстракция выделяет существенные характеристики некоторого объекта, отличающие его от всех других видов объектов и, таким образом, четко определяет его концептуальные границы с точки зрения наблюдателя.

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

Наследование (inheritance) - это процесс, посредством которого один объект может приобретать свойства другого. То есть, объект может наследовать основные свойства другого объекта и добавлять к ним свойства и методы, характерные только для него.

Наследование делится на два вида:

  • 1. одиночное наследование - класс (он же подкласс) имеет один и только один суперкласс (предок) ;
  • 2. множественное наследование - класс может иметь любое количество предков (в Java запрещено).

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

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

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

Краеугольным камнем наследования и полиморфизма предстает следующая парадигма: «объект подкласса может использоваться всюду, где используется объект суперкласса».

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

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

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

Основываясь на истории развития программирования, можно отметить следующие две сменяющие друг друга тенденции:

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

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

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

  • 1. Первое поколение (1954-1958) :
    • - FORTRAN I - математические формулы;
    • - ALGOL -58 -математические формулы;
    • - FLOWMATIC - математические формулы;
    • - IPL V - математические формулы.
  • 2. Второе поколение (1959-1961) :
    • - FORTRAN II - подпрограммы, раздельная компиляция%
    • - ALGOL-60 - блочные структуры, типы данных;
    • - COBOL - описание данных, работа с файлами.
  • 3. Третье поколение (1962-1970) :
    • - PL/1 FORTRAN+ALGOL+COBOL;
    • - ALGOL-68 более строгий преемник ALGOL-60;
    • - PASCAL - более простой преемник ALGOL-60;
    • - SIMULA - классы, абстрактные данные.

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

Первое поколение языков программирования были ограничены следующими особенностями:

  • - малым объемом оперативной памяти;
  • - несовершенством системы ввода-вывода.

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

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

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

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

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

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

Первым языком, в котором нашли свое выражение идеи построения программ на основе данных и объектов стал язык Simula 67. Концепции, заложенные в языке Simula получили свое развитие в серии языков Smaltalk-72, -74, -76, -80, а также в языках C++ и Objective C. При внесении объектно-ориентированного подхода в язык Pascal появился язык Object Pascal. В 90-х годах компания Sun представила миру язык Java, как воплощение идеи платформенной независимости и наиболее полную реализацию концепций объектно-ориентированного программирования, положенных в основу языков Simula 67, Smalltalk, C++.

Объектно-ориентированные системы предъявляют повышенные требования к аппаратуре. Практика использования ТМООП на IBM PC/AT показала замедление скорости выполнения программ в 5-7 раз по сравнению с аналогичными программами на Си или Паскале. При этом время получения готовой программы сократилось в 2-3 раза, программы стали выглядеть яснее, лучше приспособлены для повторного использования. Далее рассматриваются примеры технологий создания программных обеспечений различных компаний-поставщиков.

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

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

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

Терминология объектно-ориентированного программирования

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

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

Объект – экземпляр класса.

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

Состояние объекта – набор текущих значений полей объекта.

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

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

Член класса – поля, методы и свойства класса.

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

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

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

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

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

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

Преимущества объектно-ориентированного программирования

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

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

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

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

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


    Диаграмма классов или иерархия наследования "Транспортные средства". Белые квадраты обозначают абстрактные классы.

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

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

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

Некоторые элементы современного объектно-ориентированного программирования

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

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

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

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

Недостатки объектно-ориентированного программирования

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

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

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

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

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

Ладно. Введение это очень весело, но вы его все равно не читаете, так что кому интересно - добро пожаловать под кат!

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



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

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

Ключевые моменты:

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

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

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

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

Основные понятия:

- Инструкция
- Состояние

Порожденные понятия:

- Присваивание
- Переход
- Память
- Указатель

Как основную:
- Языки ассемблера
- Fortran
- Algol
- Cobol
- Pascal
- C
- C++
- Ada
Как вспомогательную:
- Python
- Ruby
- Java
- C#
- PHP
- Haskell (через монады)

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

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



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

Основоположниками структурного программирования были такие знаменитые люди как Э. Дейкстра и Н. Вирт.

Языками-первопроходцами в этой парадигме были Fortran, Algol и B, позже их приемниками стали Pascal и C.

Ключевые моменты:

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

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

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

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

Основные понятия:

- Блок
- Цикл
- Ветвление

Языки поддерживающие данную парадигму:

Как основную:
- C
- Pascal
- Basic
Как вспомогательную:
- C#
- Java
- Python
- Ruby
- JavaScript

Поддерживают частично:
- Некоторые макроассемблеры (через макросы)

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

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



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

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

Этим понятием на этот раз была процедура.

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

Ключевые моменты:

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

В современном программировании процедура может иметь несколько точек выхода (return в C-подобных языках), несколько точек входа (с помощью yield в Python или статических локальных переменных в C++), иметь аргументы, возвращать значение как результат своего выполнения, быть перегруженной по количеству или типу параметров и много чего еще.

Основные понятия:

- Процедура

Порожденные понятия:

- Вызов
- Аргументы
- Возврат
- Рекурсия
- Перегрузка

Языки поддерживающие данную парадигму:

Как основную:
- C
- C++
- Pascal
- Object Pascal
Как вспомогательную:
- C#
- Java
- Ruby
- Python
- JavaScript

Поддерживают частично:
- Ранний Basic

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

Модульное программирование



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

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

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

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

Ключевые моменты:

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

Например файл List.mod включающий в себя класс List
и функции для работы с ним - модуль.

Папка Geometry, содержащая модули Shape, Rectangle и Triangle - тоже модуль, хоть и некоторые языки разделяют понятие модуля и пакета (в таких языках пакет - набор модулей и/или набор других пакетов).

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

Основные понятия:

- Модуль
- Импортирование

Порожденные понятия:

- Пакет
- Инкапсуляция

Языки поддерживающие данную парадигму:

Как основную:
- Haskell
- Pascal
- Python
Как вспомогательную:
- Java
- C#
- ActionScript 3

Поддерживают частично:
- C/C++

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

Вместо заключения

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

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

Загрузка...
Top