Бертран Мейер - Основы объектно-ориентированного программирования
- Название:Основы объектно-ориентированного программирования
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Бертран Мейер - Основы объектно-ориентированного программирования краткое содержание
Фундаментальный учебник по основам объектно-ориентированного программирования и инженерии программ. В книге подробно излагаются основные понятия объектной технологии – классы, объекты, управление памятью, типизация, наследование, универсализация. Большое внимание уделяется проектированию по контракту и обработке исключений, как механизмам, обеспечивающим корректность и устойчивость программных систем.
В книге Бертрана Мейера рассматриваются основы объектно-ориентированного программирования. Изложение начинается с рассмотрения критериев качества программных систем и обоснования того, как объектная технология разработки может обеспечить требуемое качество. Основные понятия объектной технологии и соответствующая нотация появляются как результат тщательного анализа и обсуждений. Подробно рассматривается понятие класса - центральное понятие объектной технологии. Рассматривается абстрактный тип данных, лежащий в основе класса, совмещение классом роли типа данных и модуля и другие аспекты построения класса. Столь же подробно рассматриваются объекты и проблемы управления памятью. Большая часть книги уделена отношениям между классами – наследованию, универсализации и их роли в построении программных систем. Важную часть книги составляет введение понятия контракта, описание технологии проектирования по контракту, как механизма, обеспечивающего корректность создаваемых программ. Не обойдены вниманием и другие важные темы объектного программирования – скрытие информации, статическая типизация, динамическое связывание и обработка исключений. Глубина охвата рассматриваемых тем делает книгу Бертрана Мейера незаменимой для понимания основ объектного программирования.
Основы объектно-ориентированного программирования - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Впрочем, как замечает Страуструп, это решение некорректно: версии родителей дважды вызывают исходную версию display класса WINDOW , что приведет к появлению "мусора" на экране. Для исправления ситуации добавим еще один класс, получив тройку наследников класса WINDOW :
indexing
note: "Это корректная версия"
class WINDOW_WITH_BORDER_AND_MENU inherit
WINDOW_WITH_BORDER
redefine
display
export {NONE}
draw_border
end
WINDOW_WITH_MENU
redefine
display
export {NONE}
draw_menu
end
WINDOW
redefine display end
feature
display is
-- Рисует окно,его рамку и меню.
do
Precursor {WINDOW}
draw_border
draw_menu
end
...
end
Заметьте, что компоненты draw_border и draw_menu в новом классе являются скрытыми, поскольку мы не видим причин, по которым клиенты WINDOW_WITH_BORDER_AND_MENU могли бы их вызывать непосредственно.
Несмотря на активное применение дублируемого наследования, класс переопределяет все унаследованные им варианты display , что делает выражения selectненужными. В этом состоит преимущество спецификатора Precursor в сравнении с репликацией компонентов.
Неплохим тестом на понимание дублируемого наследования станет решение этой задачи без применения Precursor , путем репликации компонентов промежуточных классов. При этом, разумеется, вам понадобится select(см. упражнение 15.10).
В полученном варианте класса присутствует лишь совместное использование, но не репликация компонентов. Расширим пример Страуструпа: пусть WINDOW имеет запрос id (возможно, целого типа), направленный на идентификацию окон. Если идентифицировать любое окно только одним "номером", то id будет использоваться совместно, и нам не придется ничего менять. Если же мы хотим проследить историю окна, то экземпляр WINDOW_WITH_BORDER_AND_MENU будет иметь три id - независимых "номера". Новый текст класса комбинирует совместное использование и репликацию id (изменения в тексте класса помечены стрелками):
indexing
note: "Усложненная версия с независимыми id."
class WINDOW_WITH_BORDER_AND_MENU inherit
WINDOW_WITH_BORDER
rename
id as border_id
redefine
display
export {NONE}
draw_border
end
WINDOW_WITH_MENU
rename
id as menu_id
redefine
display
export {NONE}
draw_menu
end
WINDOW
rename
id as window_id
redefine
display
select
window_id
end
feature
.... Остальное, как ранее...
end
Обратите внимание на необходимость выбора ( select) одного из вариантов id .
Дублируемое наследование и универсальность
В завершение мы должны рассмотреть особый случай дублируемого наследования. Он касается компонентов, содержащих родовые параметры. Рассмотрим следующую схему (подобная ситуация может возникнуть не только при прямом, но и при косвенном дублируемом наследовании):
class A [G] feature
f: G;...
end
class B inherit
A [INTEGER]
A [REAL]
end
В классе B по правилу дублируемого наследования компонент f должен использоваться совместно. Но из-за универсализации возникает неоднозначность, - какой результат должен возвращать компонент - real или integer ? Та же проблема возникнет, если f имеет параметр типа G .
Подобная неоднозначность недопустима. Отсюда правило:
Универсальность в правиле дублируемого наследования
Тип компонента, совместно используемого в правиле дублируемого наследования, а также тип любого из его аргументов не может быть родовым параметром класса, от которого произошло дублируемое наследование компонента.
Для устранения неоднозначности можно выполнить переименование в точке наследования.
Правила об именах
(В этом разделе мы только формализуем сказанное выше, поэтому при первом чтении книги его можно пропустить.)
Мы уже видели, что в случае возможной неоднозначности конфликты имен пресекаются, хотя некоторые ситуации бывают вполне корректны. Чтобы в представлении множественного и дублируемого наследования не оставить никакой неоднозначности, полезно обобщить ограничения на конфликт имен в едином правиле: Заканчивая этот раздел, сведем изложенный ранее материал в единое правило:
Конфликты имен: определение и правило
В классе, образованном в результате множественного наследования, возникает конфликт имен, если два компонента, наследованные от разных родителей, имеют одно и то же финальное имя.
Конфликт имен делает класс некорректным за исключением следующих случаев:
1Оба компонента унаследованы от общего предка, и ни один из них не получен повторным объявлением версии предка.
2Оба компонента имеют совместимые сигнатуры, и, по крайней мере, один из них наследуется в отложенной форме.
3Оба компонента имеют совместимые сигнатуры и переопределяются в новом классе.
Ситуация (1) описывает совместное использование при дублируемом наследовании.
Для случая (2) "наследование в отложенной форме" возможно по двум причинам: либо отложенная форма задана родительским классом, либо компонент был эффективным, но порожденный класс отменил его реализацию ( undefine).
Ситуации (2) и (3) рассматриваются отдельно, однако, их можно представить как один вариант - вариант соединения (join). Переходя к n компонентам ( n >= 2 ), можно сказать, что ситуации (2) и (3) возникают, когда от разных родителей класс принимает n одноименных компонентов с совместимыми сигнатурами. Конфликт имен не делает класс некорректным, если эти компоненты могут быть соединены, иными словами:
[x].все n компонентов отложены, так что некому вызвать конфликт определений;
[x].существует единственный эффективный компонент. Его реализация станет реализацией остальных компонентов;
Читать дальшеИнтервал:
Закладка: