Категории
Самые читаемые
Лучшие книги » Компьютеры и Интернет » Прочая околокомпьтерная литература » Основы объектно-ориентированного программирования - Бертран Мейер

Основы объектно-ориентированного программирования - Бертран Мейер

Читать онлайн Основы объектно-ориентированного программирования - Бертран Мейер

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 149 150 151 152 153 154 155 156 157 ... 188
Перейти на страницу:

[x]. Переопределение меняет компонент, но сохраняет его имя.

[x]. Переименование меняет имя, но сохраняет компонент.

При помощи переопределения можно добиться того, чтобы одно и то же имя компонента ссылалось на фактически различные компоненты в зависимости от типа объекта, к которому оно применяется (в этом случае говорят о динамическом типе соответствующей сущности). Это - семантический механизм.

Смена имен - это синтаксический механизм, позволяющий ссылаться на один и тот же компонент, фигурирующий в разных классах под разными именами.

Иногда то и другое можно совмещать:

class SANTA_BARBARA inherit

LONDON

rename

foo as fog

redefine

fog

end

...

Если, как и раньше, l: LONDON; s: SANTA_BARBARA, и выполнено присваивание l := s, то оба вызова l.foo, s.fog включают переопределенную версию компонента fog, объявление которого должно появиться в предложении feature класса.

Заметьте: redefine содержит уже новое имя компонента. Это нормально, поскольку под этим именем компонент известен классу. Именно поэтому rename должно находиться выше всех остальных предложений наследования (таких, как redefine и пока неизвестные читателю export, undefine, select). После выполнения rename компонент теряет свой прежний идентификатор и становится известным под новым именем классу, его потомкам и его клиентам.

Подбор локальных имен

Возможность переименования наследуемого компонента небезынтересна и при отсутствии конфликта имен. Она позволяет разработчику класса подбирать подходящие имена для всех компонентов, как описанных в самом классе, так и унаследованных от предков.

Имя, под которым класс наследует компонент предка, может ничего не говорить клиентам класса. Его выбор определялся интересами клиентов предка, в то время как новый класс вписан в новый контекст и представляет иную абстракцию с собственной системой понятий. Смена имен позволяет решить возникающие проблемы, разделяя компоненты и их имена.

Хорошим примером является класс WINDOW, порожденный от класса TREE. Последний описывает иерархическую структуру, единую для всех деревьев, в том числе и для окон, но имена, понятные в исходном контексте, могут не подходить для интерфейса между WINDOW и его клиентами. Смена имен дает возможность привести их в соответствие с местными обычаями:

class WINDOW inherit

TREE [WINDOW]

rename

child as subwindow, is_leaf as is_terminal, root as screen,

arity as child_count, ...

end

RECTANGLE

feature

... Характерные компоненты window ...

end

Аналогично, класс TREE, который сам порожден от CELL, может сменить имя right на right_sibling и т.д. Путем смены имен класс может создать удобный набор наименований своих "служб" вне зависимости от истории их создания.

Играем в имена

Смена имен подчеркивает важность именования - как компонентов, так и классов - в практике ОО-разработки ПО. Формально, класс - это отображение имен компонентов в сами компоненты. Компоненты известны остальному миру благодаря именам.

В последней лекции будет дан ряд правил выбора имен компонентов. Заметим, что предпочтение следует отдавать общеизвестным именам: count, put, item, remove, ... - выбор которых подчеркивает общность абстракций, существующую, несмотря на объективные различия классов. Придерживаясь этого стиля, вы увеличите вероятность конфликта имен при множественном наследовании, но отчасти избавитесь от переименований, имевших место в случае с классом WINDOW. Но каким бы правилам не отдавалось предпочтение, должна быть обеспечена гибкость в подборе имен, отвечающих потребностям каждого класса.

Использование родительской процедуры создания

Еще один пример иллюстрирует типичный случай переименования процедуры создания класса. Вспомните класс ARRAYED_STACK, полученный порождением от STACK и ARRAY. Процедура создания ARRAY размещает в памяти массив с заданными границами:

make (minb, maxb: INTEGER) is

-- создать массив с границами minb и maxb

-- (пустой если minb > maxb)

do ... end

Для создания стека необходимо создать массив, позволяющий вместить заданное число элементов. Реализация основана на процедуре создания ARRAY:

class ARRAYED_STACK [G] inherit

STACK [G]

redefine change_top end

ARRAY [G]

rename

count as capacity, put as array_put, make as array_make

end

creation

make

feature -- Initialization

make (n: INTEGER) is

-- Создать стек, допускающий размещение n элементов.

require

non_negative_size: n >= 0

do

array_make (1, n)

ensure

capacity_set: capacity = n

empty: count = 0

end

... Другие компоненты ...

invariant

count >= 0; count <= capacity

end

Заметим, что выполнение соглашений об именах - выбор make как стандартного имени базовой процедуры создания - привело бы к конфликту, который, впрочем, не возникает благодаря переименованию, устраняющему заодно двусмысленность в отношении count и put. Оба имени встречаются в каждом классе.

Плоские структуры

Смена имен - лишь одно из средств, используемых мастером наследования для построения полноценных классов, удовлетворяющих потребностям своих клиентов. Другим таким средством является переопределение. В этой и следующей лекции мы увидим еще несколько таких механизмов: отмену определений (undefinition), соединение (join), выделение (select), скрытие потомков (descendant hiding). Мощь этих комбинируемых механизмов делает наследование излишне заметным, поэтому иногда возникает необходимость в существовании версии класса, свободной от наследования, - плоской форме (flat form).

Плоская форма класса

Наследование - это скорее инструмент поставщика класса, чем клиента; это прежде всего внутренний механизм эффективного построения классов. И действительно, клиенту нужно знать о наследовании и структуре семейства классов ровно столько, чтобы он мог применять полиморфизм и динамическое связывание.

Как следствие, у нас должна быть возможность представить класс в самодостаточном виде независимо от его генеалогии. Это особенно важно, когда наследование служит для разделения различных компонентов сложной абстракции, как в случае концепции окон, частями которой являются деревья и прямоугольники.

Эту задачу решает плоская форма класса. Но вам не придется ее создавать. Ее построит один из инструментов среды разработки, который можно запустить, введя команду сценария (flat class_name) или щелкнув по соответствующей пиктограмме.

Плоская форма класса C - это корректная запись класса, имеющая, - с точки зрения клиента, не использующего полиморфизм, - ту же семантику, что и класс C, но лишенная всех предложений наследования. Именно так выглядел бы любой класс, если бы его создатель не мог пользоваться наследованием. Построение плоской формы предполагает:

[x]. устранение предложения inherit, если оно есть;

[x]. сохранение в неизменном виде всех определений и переопределений из C;

[x]. введение в класс объявлений всех унаследованных компонентов, скопированных из соответствующих классов-родителей, с учетом всех указанных в inherit преобразований: переименования, переопределения, отмены определений, выделения (select), объединения компонентов;

[x]. добавление к каждому унаследованному компоненту строки комментария вида: from ANCESTOR, где указано имя ближайшего предка, (пере)определившего компонент (а в случае объединения компонентов - победившая сторона);

[x]. восстановление полной формы предусловий и постусловий унаследованных методов (по правилам наследования утверждений, изложенным в следующей лекции);

[x]. восстановление полного инварианта класса как конъюнкции (and) всех родительских инвариантов с последующим преобразованием в случае применения переименованных или выделенных компонентов.

1 ... 149 150 151 152 153 154 155 156 157 ... 188
Перейти на страницу:
На этой странице вы можете бесплатно скачать Основы объектно-ориентированного программирования - Бертран Мейер торрент бесплатно.
Комментарии
Открыть боковую панель