Пример повышенной сложности
Пример повышенной сложности
Вот более сложный пример применения разных аспектов дублируемого наследования.
Проблема, близкая по духу нашему примеру, возникла из интересного обсуждения в основной книге по C++ [Stroustrup 1991].
Рассмотрим класс WINDOW с процедурой display и двумя наследниками: WINDOW_WITH_BORDER и WINDOW_WITH_MENU. Эти классы описывают абстрактные окна, первое из них имеет рамку, а второе поддерживает меню. Переопределяя display, каждый класс выводит на экран стандартное окно, а затем добавляет к нему рамку (в первом случае) и меню (во втором).
Опишем окно с рамкой и с поддержкой меню. В результате мы породим класс WINDOW_WITH_BORDER_AND_MENU.
Рис. 15.24. Варианты окна
Переопределим метод display в новом классе; новая версия вначале вызывает исходную, затем строит рамку, а потом строит меню. Исходный класс WINDOW имеет вид:
class WINDOW feature
display is
-- Отобразить окно (общий алгоритм)
do
...
end
... Другие компоненты ...
end
Наследник WINDOW_WITH_BORDER осуществляет вызов родительской версии display и затем отображает рамку. В дублируемом наследовании нет необходимости, достаточно воспользоваться механизмом Precursor:
class WINDOW_WITH_BORDER inherit
WINDOW
redefine display end
feature -- Output
display is
-- Рисует окно и его рамку.
do
Precursor
draw_border
end
feature {NONE} -- Implementation
draw_border is do ... end
...
end
Обратите внимание на процедуру draw_border, рисующую рамку окна. Она скрыта от клиентов класса WINDOW_WITH_BORDER (экспорт классу NONE), поскольку для них вызов draw_border не имеет смысла. Класс WINDOW_WITH_MENU аналогичен:
class WINDOW_WITH_MENU inherit
WINDOW
redefine display end
feature -- Output
display is
-- Рисует окно и его меню.
do
Precursor
draw_menu
end
feature {NONE} -- Implementation
draw_menu is do ... end
...
end
Осталось описать общего наследника WINDOW_WITH_BORDER_AND_MENU этих двух классов, дублируемого потомка WINDOW. Предпримем первую попытку:
indexing
WARNING: "Первая попытка - версия не будет работать корректно!"
class WINDOW_WITH_BORDER_AND_MENU inherit
WINDOW_WITH_BORDER
redefine display end
WINDOW_WITH_MENU
redefine display end
feature
display is
-- Рисует окно,его рамку и меню.
do
Precursor {WINDOW_WITH_BORDER}
Precursor {WINDOW_WITH_MENU}
end
...
end
Заметьте: при каждом обращении к Precursor мы вынуждены называть имя предка. Каждый предок имеет собственный компонент display, переопределенный под тем же именем.
Впрочем, как замечает Страуструп, это решение некорректно: версии родителей дважды вызывают исходную версию 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.
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКЧитайте также
5.4.3. Только Linux: указание файлового времени повышенной точности
5.4.3. Только Linux: указание файлового времени повышенной точности Ядра Linux 2.6 и более поздние предоставляют в struct stat три дополнительных поля. Они предусматривают точность файлового времени до наносекунд:st_atime_nsec Наносекундная компонента времени доступа к файлу.st_mtime_nsec
Функции повышенной точности BCMath
Функции повышенной точности BCMath bcaddСложение двух чисел произвольной точности.Синтаксис:string bcadd(string left_operand, string right_operand [, int scale]);Эта функция возвращает строковое представление суммы двух параметров (left_operand + right_operand) с точностью, которая указана в необязательном параметре
1.9 Сложности практической реализации
1.9 Сложности практической реализации Стек ввода-вывода подсистемы хранения в семействе Windows Server описан в этой главе довольно подробно. Но помните, что стек подсистемы хранения не обслуживает устройства, поддерживающие несколько протоколов.Чтобы повысить надежность и
2.7 Сложности практической реализации
2.7 Сложности практической реализации В новой модели драйверов Storport оптимизированы функции ввода-вы- вода и общая производительность системы управления. Однако системный администратор и менеджеры по закупкам в информационных отделах компаний должны знать, что новая
3.8 Сложности практической реализации
3.8 Сложности практической реализации Начиная с Windows 2000, компания Microsoft предоставляет новую модель мини-драйвера, которая позволяет независимым поставщикам создавать сетевые файловые системы. От поставщиков требуется создать мини-драйвер, который поддерживает
5.9 Сложности практической реализации
5.9 Сложности практической реализации Дорогостоящие подсистемы хранения, которые могут отслеживать метаданные для каждого сектора, позволяют намного эффективнее выполнять операции резервного копирования и восстановления, так как изменения отслеживаются очень точно и
6.7 Сложности практической реализации
6.7 Сложности практической реализации В Windows 2000 впервые появилась поддержка динамических дисков. Следует обратить внимание на процесс улучшения поддержки динамических дисков компанией Microsoft, что понадобится при установке системы и предустановке дисков независимыми
7.10 Сложности практической реализации
7.10 Сложности практической реализации Интересно наблюдать, как поддержка интерфейса WMI развивается от рекомендуемой до обязательной в наборах программной разработки Microsoft и в требованиях этой компании. Развитие WMI происходит согласно устоявшейся практике Microsoft, которая
8.3 Сложности практической реализации
8.3 Сложности практической реализации Администраторы и руководители отделов информационных технологий должны обратить внимание на то, ч; го поддержка протокола iSCSI не обеспечена в базовой версии Windows Server 2003. Таким образом, все системы на базе iSCSI, которые будут
9.5 Сложности практической реализации
9.5 Сложности практической реализации Использование массивов RAID является весьма привлекательным решением, поскольку позволяет избежать значительных потерь производительности и обеспечить отказоустойчивость. Было создано несколько схем массивов RAID, которые
10.6 Сложности практической реализации
10.6 Сложности практической реализации Компания Microsoft намерена превратить Windows в полноценную платформу для организации хранилищ данных. Возможности новых версий Windows NT ясно подчеркивают эту тенденцию. Безусловно, Microsoft будет играть важную роль в индустрии корпоративных
13.1.1. Три источника сложности
13.1.1. Три источника сложности Вопросы о простоте, сложности и верном размере программного обеспечения вызывают бурные споры в Unix-сообществе. Unix-программисты развили такое мировоззрение, согласно которому простота — это красота, изящество и добро, а сложность — уродство,
13.1.1. Три источника сложности
13.1.1. Три источника сложности Вопросы о простоте, сложности и верном размере программного обеспечения вызывают бурные споры в Unix-сообществе. Unix-программисты развили такое мировоззрение, согласно которому простота — это красота, изящество и добро, а сложность — уродство,
13.1.4. Диаграмма видов сложности
13.1.4. Диаграмма видов сложности Выше были показаны две различные шкалы для анализа сложности. Данные шкалы фактически перпендикулярны друг другу. Рис. 13.1 может помочь при выяснении связей. В каждом из девяти блоков на рисунке приведен общий источник определенного вида
Часть 4. Материал повышенной сложности
Часть 4. Материал повышенной сложности Итак, мы вплотную подошли к изучению очень сложных и необычных аспектов написания сценариев. В этой части мы попытаемся "сбросить покров тайны" и заглянуть за пределы известного нам мира (представьте себе путешествие по территории,