Бертран Мейер - Основы объектно-ориентированного программирования
- Название:Основы объектно-ориентированного программирования
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Бертран Мейер - Основы объектно-ориентированного программирования краткое содержание
Фундаментальный учебник по основам объектно-ориентированного программирования и инженерии программ. В книге подробно излагаются основные понятия объектной технологии – классы, объекты, управление памятью, типизация, наследование, универсализация. Большое внимание уделяется проектированию по контракту и обработке исключений, как механизмам, обеспечивающим корректность и устойчивость программных систем.
В книге Бертрана Мейера рассматриваются основы объектно-ориентированного программирования. Изложение начинается с рассмотрения критериев качества программных систем и обоснования того, как объектная технология разработки может обеспечить требуемое качество. Основные понятия объектной технологии и соответствующая нотация появляются как результат тщательного анализа и обсуждений. Подробно рассматривается понятие класса - центральное понятие объектной технологии. Рассматривается абстрактный тип данных, лежащий в основе класса, совмещение классом роли типа данных и модуля и другие аспекты построения класса. Столь же подробно рассматриваются объекты и проблемы управления памятью. Большая часть книги уделена отношениям между классами – наследованию, универсализации и их роли в построении программных систем. Важную часть книги составляет введение понятия контракта, описание технологии проектирования по контракту, как механизма, обеспечивающего корректность создаваемых программ. Не обойдены вниманием и другие важные темы объектного программирования – скрытие информации, статическая типизация, динамическое связывание и обработка исключений. Глубина охвата рассматриваемых тем делает книгу Бертрана Мейера незаменимой для понимания основ объектного программирования.
Основы объектно-ориентированного программирования - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
[x].Для наследуемого компонента без переименования - финальное имя компонента (рекурсивно) в том родительском классе, от которого оно унаследовано.
[x].Для переименованного компонента - имя, полученное при переименовании.
Правило одного имени
Разные эффективные компоненты одного класса не могут иметь одно и то же финальное имя.
Конфликт имен происходит в том случае, когда два разных по сути компонента, оба эффективные (реализованные), имеют одно финальное имя. Такой конфликт делает класс некорректным, однако ситуацию легко исправить, добавив надлежащее предложение переименования.
Ключевым в тексте правила является слово " разные". Если под одним именем мы наследуем от родителей компонентов их общего предка, действует принцип совместного использования компонентов: наследуется один компонент, и конфликта имен не возникает.
Запрет на дублирование имен касается лишь эффективных компонентов. Если один или более компонентов с омонимичными именами являются отложенными, их можно фактически слитьвоедино, поскольку отсутствует несовместимость реализаций. Подробнее мы поговорим об этом чуть ниже.
Приведенные правила просты и интуитивны. Чтобы в последний раз нам убедиться в их правильном понимании, построим простой пример, демонстрирующий допустимые и недопустимые варианты наследования.
Рис. 15.20. Два варианта наследования
class A feature
this_one_OK: INTEGER
end
class B inherit A feature
portends_trouble: REAL
end
class C inherit A feature
portends_trouble: CHARACTER
end
class D inherit
-- Это неправильный вариант!
B
C
end
Класс D наследует this_one_OK дважды, один раз от B , другой раз - от C . Конфликта имен не возникает, поскольку данный компонент будет использоваться совместно. На самом деле, это - один компонент предка A .
Два компонента portend_trouble ("предвещающие беду") заслуженно получили такое имя. Они различны, потому их появление в D ведет к конфликту имен, делая класс некорректным. (У них разные типы, но и одинаковые типы никак не повлияли бы на ход нашего обсуждения.)
Переименовав один из компонентов, мы с легкостью сделаем D корректным:
class D inherit
-- Этот вариант класса теперь полностью корректен.
B
rename portends_trouble as does_not_portend_trouble_any_more end
C
end
Конфликт переопределений
Пока в ходе наследования мы меняли лишь имена. А что, если промежуточный предок, такой, как B или C (см. последний рисунок), переопределит дублируемо наследуемый компонент? При динамическом связывании это может привести к неоднозначности в D .
Проблему решают два простых механизма: отмена определения (undefinition) и выделение (selection). Как обычно, вы сами примете участие в их разработке и убедитесь в том, что при четкой постановке задачи нужная конструкция языка становится совершенно очевидной.
Пусть дублируемо наследуемый компонент переопределяется в одной из ветвей:
Рис. 15.21. Переопределение - причина потенциальной неоднозначности
Класс B переопределяет f . Поэтому в D этот компонент представлен в двух вариантах: результат переопределения в B и исходный вариант из A , полученный через класс C . (Можно предполагать, что и C переопределяет f , но это не внесет в наше рассуждение ничего нового.) Такое положение дел отличается от предыдущих случаев, в которых мы имели лишь один вариант компонента, возможно, наследуемый под разными именами.
Что произойдет в результате? Ответ зависит от того, под одним или разными именами класс D наследует варианты компонентов. Подразумевает ли дублируемое наследование репликацию или совместное использование? Рассмотрим эти случаи по порядку.
Конфликт при совместном использовании: отмена определения и соединение компонентов
Предположим вначале, что две версии наследуются под одним и тем же именем. Это случай совместного использования. Одному имени должен в точности соответствовать один компонент. Возможны три ситуации.
1Если одна версия отложена, а другая - эффективна, то сложностей не возникает, будет использован эффективный вариант компонента. Заметим, что этот случай явно предусмотрен правилом одного имени: речь в нем идет лишь о конфликте имен двух эффективных версий.
2Каждая версия эффективна, однако обе они переопределяются в D в предложении redefine. Проблемы снова не возникает, поскольку обе версии сливаются в одну, переопределяемую в тексте класса.
3Обе версии эффективны, но обе не переопределяются, тогда действительно возникает конфликт имен. Класс D будет отвергнут, как нарушающий правило одного имени.
Нередко (3) означает ошибку: создана неоднозначность имен, и ее необходимо исправить. Тривиальным решением проблемы является переименованиеодного из вариантов, но тогда мы от рассматриваемого случая совместного использования переходим к репликации, изучаемой ниже.
Есть и другая, более изощренная возможность решения конфликта (3). Она состоит в том, чтобы позволить одному из вариантов "взять верх" над другим. Дальнейшее очевидно - свести эту ситуацию к (1), сделав один из двух вариантов отложенным.
Правила переопределения дают возможность переопределить компонент f как отложенный, хотя для этого и потребуется ввести промежуточный класс, скажем C' , - наследника C , единственная роль которого - в переопределении отложенного f . Затем класс D должен быть порожден не от C , а от C' . Сложно и некрасиво. Вместо этого нам нужен простой языковой механизм: undefine. В секции наследования класса он приводит к появлению нового предложения:
class D inherit
B
C
undefine f end
feature
...
end
Синтаксически предложение undefineследует за rename (всякая отмена определения должна действовать на окончательный вариант имени компонента), но до redefine(прежде, чем что-то переопределять, мы должны позаботиться об отмене ненужных определений).
Признаком того, что предлагаемый языковой механизм желателен, почти всегда является его направленность на решение нескольких проблем (соответственно, плохой механизм создает больше проблем, чем решает). Механизм отмены определений отвечает этому требованию: он позволяет соединятькомпоненты в условиях множественного (не обязательно - дублируемого) наследования. Пусть мы хотим свести воедино две абстракции:
Читать дальшеИнтервал:
Закладка: