51. Современные объектно-ориентированные технологии
Объе́ктно-ориенти́рованное программи́рование (ООП) — методология программирования, основанная на представлении программы в виде совокупности объектов, каждый из которых является экземпляром определенного класса[1], а классы образуют иерархию наследования[2][3].
Необходимо обратить внимание на следующие важные части этого определения: 1) объектно-ориентированное программирование использует в качестве основных логических конструктивных элементов объекты, а не алгоритмы; 2) каждый объект является экземпляром определенного класса; 3) классы образуют иерархии. Программа считается объектно-ориентированной, только если выполнены все три указанных требования. В частности, программирование, не использующее наследование, называется не объектно-ориентированным, а программированием с помощью абстрактных типов данных[4].
Содержание
- 1 Основные понятия
- 2 Классификация подвидов ООП
- 3 История
- 4 Определение ООП и его основные концепции
- 5 Особенности реализации
- 6 Проектирование программ в целом
- 7 Различные ООП-методологии
- 7.1 Компонентное программирование
- 7.2 Прототипное программирование
- 7.3 Класс-ориентированное программирование
- 8 Производительность объектных программ
- 9 Критика ООП
- 10 Объектно-ориентированные языки
- 11 См. также
- 12 Примечания
- 13 Литература
- 14 Ссылки
Основные понятия
Абстрагирование означает выделение значимой информации и исключение из рассмотрения незначимой. В ООП рассматривают лишь абстракцию данных (нередко называя её просто «абстракцией»), подразумевая набор значимых характеристик объекта, доступный остальной программе.
Инкапсуляция — свойство системы, позволяющее объединить данные и методы, работающие с ними, в классе. Одни языки (например, С++, Java или Ruby) отождествляют инкапсуляцию с сокрытием, но другие (Smalltalk, Eiffel, OCaml) различают эти понятия.
Наследование — свойство системы, позволяющее описать новый класс на основе уже существующего с частично или полностью заимствующейся функциональностью. Класс, от которого производится наследование, называется базовым, родительским или суперклассом. Новый класс — потомком, наследником, дочерним или производным классом.
Полиморфизм подтипов (в ООП называемый просто «полиморфизмом») — свойство системы, позволяющее использовать объекты с одинаковым интерфейсом без информации о типе и внутренней структуре объекта. Другой вид полиморфизма — параметрический — в ООП называют обобщённым программированием.
Класс — универсальный, комплексный тип данных, состоящий из тематически единого набора «полей» (переменных более элементарных типов) и «методов» (функций для работы с этими полями), то есть он является моделью информационной сущности с внутренним и внешним интерфейсами для оперирования своим содержимым (значениями полей). В частности, в классах широко используются специальные блоки из одного или чаще двух спаренных методов, отвечающих за элементарные операции с определенным полем (интерфейс присваивания и считывания значения), которые имитируют непосредственный доступ к полю. Эти блоки называются «свойствами» и почти совпадают по конкретному имени со своим полем (например, имя поля может начинаться со строчной, а имя свойства — с заглавной буквы). Другим проявлением интерфейсной природы класса является то, что при копировании соответствующей переменной через присваивание, копируется только интерфейс, но не сами данные, то есть класс — ссылочный тип данных. Переменная-объект, относящаяся к заданному классом типу, называется экземпляром этого класса. При этом в некоторых исполняющих системах класс также может представляться некоторым объектом при выполнении программы посредством динамической идентификации типа данных. Обычно классы разрабатывают таким образом, чтобы обеспечить отвечающие природе объекта и решаемой задаче целостность данных объекта, а также удобный и простой интерфейс. В свою очередь, целостность предметной области объектов и их интерфейсов, а также удобство их проектирования, обеспечивается наследованием.
Сущность в адресном пространстве вычислительной системы, появляющаяся при создании экземпляра класса (например, после запуска результатов компиляции и связывания исходного кода на выполнение).
Классификация подвидов ООП
Лука Карделли[en] и Мартин Абади построили теоретическое обоснование ООП и классификацию на основе этого обоснования[6][7][8][9]. Они отмечают, что выделенные ими понятия и категории вместе встречаются далеко не во всех ОО-языках, большинство языков поддерживают лишь подмножества теории, а порой и своеобразные отклонения от неё.
Ключевые понятия:
- квантификация переменных типа (универсальная, экзистенциальная, ограниченная[en]);
- подтипизация[en] (англ. subtyping — отношения «супертип-подтип»);
- включение (англ. subsumption — см. принцип подстановки Барбары Лисков) — частный случай подтипизации[en] — см. подтипизация на записях;
- объект;
- объектный тип (фактически, специальная форма «записи», в число полей которой входят функции первого класса);
- класс.
Класс описывает абстрактное поведение. Объектные типы строятся на основе класса посредством добавления различных приватных полей и методов. Объект (то есть значение объектного типа, традиционно называемое «экземпляром класса») порождается конструктором на основе начальных параметров.
Традиционно перечисляемые основные принципы ООП не аппелируют к данному теоретическому обоснованию, а являются устоявшимися в сообществе догмами (что приводит к сильному разбросу вариантов изложения в разных источниках). По большей части они относятся к языкам — потомкам Алгола и Симулы; в меньшей степени — к потомкам Smalltalk (в частности, часто упоминаемый принцип сокрытия в потомках Smalltalk семантически недоступен и идеологически считается несущественным). В значительно большей степени теоретически обоснованные концепции ООП поддерживают ОО-языки, развившиеся на поприще функционального программирования: OCaml, диалекты Haskell (O’Haskell, Mondrian), successor ML. Более того, основные идеи объектного моделирования в этом случае не требуют прямой поддержки со стороны языка, а могут быть сравнительно легко эмулированы[10].
Наиболее заметные отличия в проявлении показателей качества между языками разных видов:
- В мейнстримных языках декларируемые принципы нацелены на повышение изначально низкого для императивного программирования коэффициента повторного использования кода. В полиморфно типизированных применение концепций ООП, напротив, означает очевидное его снижение из-за перехода от параметрического полиморфизма к ad hoc полиморфизму[11]. В динамически типизированных языках (Smalltalk, Python, Ruby) эти принципы используются для логической организации программы, и их влияние на коэффициент повторного использования трудно спрогнозировать — он сильно зависит от дисциплины программиста. Например, в CLOS мультиметоды одновременно являются функциями первого класса, что позволяет рассматривать их одновременно и как связанно квантифицированные[en], и как обобщённые (истинно полиморфные).
- Традиционные ОО-языки используют номинативную типизацию[en], то есть допустимость соиспользования объектов разных классов только при условии явного указания родственных отношений между классами. Для полиморфно типизированных языков характерна структурная типизация[en], то есть согласование классов между собой тем же механизмом, что и согласование числа 5 с типом int. Динамически типизированные языки также занимают здесь промежуточную позицию.
Обобщённое обоснование динамической диспетчеризации[en] (включая множественную) в середине 1990-х годов построил Джузеппе Кастанья[12][13][9].