182 18.1. Что такое объектно-ориентированное программирование?
В противоположность этому, обыкновенный абстрактный тип данных (АТД) состоит из набо-
ра значений, связанных с единственной реализацией операций над этими значениями. (Такое
статическое определение реализаций имеет как достоинства, так и недостатки по сравнению с
объектами; мы это подробно рассматриваем в §24.2.3.)
2. Инкапсуляция. Внутреннее представление объекта, как правило, недоступно за пределами его
определения: только собственные методы объекта имеют право прямо считывать или изменять его
поля.
1
Это означает, что изменения во внутреннем представлении объекта могут повлиять лишь
на небольшой, ясно определенный участок проограммы; такое ограничение значительно облегчает
чтение и поддержку больших систем.
Абстрактные типы данных предоставляют подобные же формы инкапсуляции, и делают конкрет-
ную форму представления типа видимой лишь внутри определенного участка программы (непр.,
модуля, или определения АТД), а код вне этого участка может работать со значениями типа
только с помощью операций, определенных внутри привилегированной области.
3. Наследование. Тип объекта — его интерфейс, — просто множество имен и типов его операций.
Внутреннее представление объекта не фигурирует в его типе, поскольку оно не влияет на набор
действий, которые мы можем над объектом проделывать.
Интерфейсы объектов естественным образом определяют отношение наследования. Если объект
удовлетворяет интерфейсу I, то он, разумеется, удовлетворяет всякому интерфейсу J с более уз-
ким набором операций, чем I, поскольку всякий контекст, ожидающий J-объект, может вызывать
у него только J-операции, и использование I-объекта в таком контексте является безопасным.
(Таким образом, наследование объектов подобно наследованию записей. На самом деле, в модели
объектов, разарабатываемой в этой главе, это будет одно и то же.) Способность игнорировать
часть интерфейса объекта позволяет нам писать код, обрабатывающий многие различные виды
объектов единым способом, требуя при этом только опеределенного общего набора операций.
4. Наследование реализаций. Объекты, в интерфейсах которых есть общая часть, часто будут
иметь общность и в поведении, и нам хотелось бы эту общую часть поведения реализовать лишь
однажды. В большинстве объектно-ориентированных языков такое повторное использование по-
ведения достигается при помощи структур, называемых классы — образцы, служащие для созда-
ния экземпляров объектов, — и механизма производных классов, позволяющего порождать новые
классы из старых, добавляя реализации новых методов, и по необходимости переопределяя реали-
зации отдельных старых методов. (Некоторые объектно-ориентированные языки вместо классов
используют механизм делегатов, сочетающий свойства объектов и классов.)
5. Открытая рекурсия. Еще одна удобная конструкция, имеющаяся в большинстве языков с объ-
ектами и классами, — возможность вызвать из одного тела метода другой метод того же объекта
через особую переменную по имени self (в некоторых языках this). Особенность поведения self
состоит в том, что она имеет позднее связывание, что позволяет одному методу класса вызывать
другой метод, который определяется позже, в некотором подклассе этого класса.
1
В некоторых объектно-ориентированных языках программирования, таких как Smalltalk, инкапсуляция обязательна
— извне определения объекта невозможно даже назвать имя его полей. В других языках, скажем, C или Java, поля
могут быть помечены как общедоступные (public) или приватные (private). С другой стороны, в Smalltalk все методы
объекта публично доступны, в то время как C и Java позволяют отмечать методы модификатором private, и таким
образом разрешать их вызов только из других методов того же объекта. В нашей книге мы эти детали опустим, но они
подробно рассматривались в исследовательской литературе (Pierce and Turner 1993; Fisher and Mitchell 1998; Fisher 1996a;
Fisher and Mitchell 1996; Fisher 1996b; Fisher and Reppy 1999). В то время как в большинстве объектно-ориентированных
языков инкапсуляция считается существенным свойством, в нескольких языках это не так. Мультметоды, имеющиеся в
CLOS (Bobrow, DeMichiel, Gabriel, Keene, Kiczales and Moon 1988; Kiczales, des Rivi`eres and Bobrow 1991), Cecil (Chambers
1992, 1993), Dylan (Feinberg, Keene, Matthews and Withington 1997; Shalit 1997) и KEA (Mugridge. Hamer and Hosking
1991), а также в лямбда-& исчислении Кастаньи, Гелли и Лонго (Castagna, Ghelli and Longo 1995; Castagna 1997) хранят
состояние объектов отдельно от методов, и выбирают нужный вариант тела метода во время его вызова при помощи
особых меток типа. Внутренние механизмы создания объектов, вызова методов, определения классов и т. п. в этих
языках совершенно отличны от описываемых нами в этой главе, однако они приводят почти к таким же высокоуровневым
идиомам программирования.
rev. 104