- •Введение
- •Как получить исходные тексты
- •Что требуется знать для чтения книги
- •Предисловие к первому изданию
- •Благодарности
- •1.3.Новая парадигма
- •Что читать дальше
- •Упражнения
- •2.7.3.Зацепление и связность
- •2.9. Выбор представления данных
- •Упражнения
- •Глава 3 Классы и методы
- •Упражнения
- •Глава 4 Сообщения, экземпляры и инициализация
- •Упражнения
- •Глава 5 Учебный пример: задача о восьми ферзях
- •Упражнения
- •Глава 6 Учебный пример: игра «Бильярд»
- •Упражнения
- •Глава 7 Наследование
- •7.6.Издержки наследования
- •Упражнения
- •Глава 8 Учебный пример: Пасьянс
- •8.4.1.Основание SuitPile
- •8.4.2.Колода DeckPile
- •Упражнения
- •9.1.1. «Быть экземпляром» и «включать как часть»
- •Упражнения
- •Глава 10 Подклассы и подтипы
- •Упражнения
- •Глава 11 Замещение и уточнение
- •Упражнения
- •Глава 12 Следствия наследования
- •Упражнения
- •Глава 13 Множественное наследование
- •13.1.Комплексные числа
- •Литература для дальнейшего чтения
- •Упражнения
- •Глава 14 Полиморфизм
- •Полиморфные переменные
- •Виртуальное и невиртуальное переопределение
- •Параметрическая перегрузка
- •Отложенные методы в C++
- •Обобщенные функции и шаблоны
- •Полиморфные переменные
- •Отложенные методы в Object Pascal
- •Полиморфные переменные
- •Отложенные методы в Objective-C
- •Полиморфные переменные
- •Отложенные методы в Smalltalk
- •Упражнения
- •Глава 15 Учебный пример: контейнерные классы
- •Упражнения
- •Глава 16 Пример: STL
- •Упражнения
- •Глава 17 Видимость и зависимость
- •Родственные экземпляры
- •Дружественные функции
- •Пространства имен
- •Постоянные члены
- •Упражнения
- •Глава 18 Среды и схемы разработки
- •18.1.1. Java API
- •Упражнения
- •19.5.Класс application
- •19.5.1.Класс button
- •Упражнения
- •Глава 20 Новый взгляд на классы
- •20.2.2.Класс Class
- •Упражнения
- •Глава 21 Реализация объектно-ориентированных языков
- •Литература для дальнейшего чтения
- •Упражнения
- •А.1. «Задача о восьми ферзях» на языке Apple Object Pascal
- •A.3. «Задача о восьми ферзях» на языке Java
- •A.3.1. HTML-файл для апплета Java
- •A.4. «Задача о восьми ферзях» на языке Objective-C
- •A.5. «Задача о восьми ферзях» на языке Smalltalk
- •Б.1. Версия без использования наследования
- •Б.2. Версия с использованием наследования
- •Глоссарий
converted to PDF by BoJIoc
2 Стоит, однако, привести и другую точку зрения. Следующие цитаты принадлежат Алану Голубу — программисту, консультанту и преподавателю, специализирующемуся в области ООП: «Разбухание программ является огромной проблемой. Жесткий диск в 350 Мб на моей машине может вместить операционную систему, усеченную версию компилятора и редактор, и больше ничего. В стародавние времена я мог разместить версии CP/M для тех же программ на одной-единственной дискете в 1,2 Мб... Я убежден, что большая часть этого разбухания памяти является результатом небрежного программирования»; «Если только вы не проникнетесь сознанием необходимости дисциплинировать себя, то можете закончить гигантским модулем из неподдающейся сопровождению тарабарщины, только притворяющейся компьютерной программой». — Примеч. перев.
часто минимально — два или три дополнительных ассемблерных оператора и общее увеличение времени на 10 процентов. Результаты замеров скорости различны для разных языков. Накладные расходы на посылку сообщений больше в языках программирования с динамическими типами данных (например, Smalltalk) и гораздо меньше в языках со статическими типами (C++, в частности). Эти затраты, как и другие, должны рассматриваться на фоне многих преимуществ объектно-ориентированной техники.
Некоторые языки программирования, и особенно C++, предоставляют программистам некоторое количество опций, дающих возможность уменьшить накладные расходы на посылку сообщений. Они включают в себя исключение полиморфизма из сообщений (при указании имени класса в вызовах функций) и поддержку встраиваемых (inline) процедур. Подобным образом программист на языке Delphi Pascal может выбрать методы, описанные с помощью ключевого слова dynamic, которые будут использовать механизм поиска во время выполнения или использовать методы с ключевым словом virtual, которые применяют несколько более быструю технику. Динамические методы более медленны при наследовании, но требуют меньше памяти.
7.6.4. Сложность программ
Хотя объектно-ориентированное программирование часто выдвигается как способ разрешения проблемы сложности программного обеспечения, необдуманное
использование наследования может часто просто заменить одну форму сложности на другую. Для понимания программы, использующей наследование, может потребоваться несколько сложных переходов вверх и вниз в иерархическом дереве. Эта проблема известна под именем «вверх-вниз», или «йо-йо». Мы обсудим ее в следующей главе.
Упражнения
1.Предположим, вам требуется написать программный проект на языке программирования, который не является объектно-ориентированным (например, Pascal или C). Как бы вы имитировали классы и методы? Как бы вы имитировали наследование? Сможете ли вы обеспечить множественное наследование? Обоснуйте свой ответ.
2.Мы указывали, что накладные расходы, связанные с посылкой сообщений, обычно больше, чем при традиционном вызове процедур. Как вы могли бы их измерить? Для языка программирования, поддерживающего и классы, и процедуры (C++ или Object Pascal), придумайте эксперимент для определения фактических затрат на посылку сообщений.
3.Рассмотрите три геометрических понятия: линия (бесконечна в обоих направлениях), луч (начало в фиксированной точке, бесконечен в одном направлении), сегмент (отрезок прямой с фиксированными концами). Как бы вы построили классы, представляющие эти три понятия, в виде иерархии наследования? Будет ли ваше решение другим, если вы обратите особое внимание на представление данных (на поведение)? Охарактеризуйте тип наследования, который вы использовали. Объясните ваше решение.