(Этот раздел посвящен весьма специфичному вопросу, и при первом чтении книги его можно пропустить.)
Приступая к изучению наследования, мы познакомились с простой конструкцией Precursor, позволявшей переопределяемому компоненту вызывать его исходную версию. Механизм дублируемого наследования дает возможность обратиться к более универсальному (хотя и более "тяжеловесному") решению, пригодному в тех редких случаях, когда базовых средств не хватает.
Вернемся к известному нам классу BUTTON - потомку WINDOW, переопределяющему display:
display is -- Показ кнопки на экране. do window_display special_button_actions end
где window_display выводит кнопку как обычное окно, а special_button_actions добавляет элементы, специфические для кнопки, отображая, например, ее границы. Компонент window_display в точности совпадает с WINDOW-вариантом display.
Мы уже знаем, как написать window_display, используя механизм Precursor. Если метод display переопределен в нескольких родительских классах, то желаемый класс можно указать в фигурных скобках: Precursor {WINDOW}. Того же результата можно достичь, прибегнув к дублируемому наследованию, заставив класс Button быть потомком двух классов Window:
indexing WARNING: "Это первая попытка - данная версия некорректна!" class BUTTON inherit WINDOW redefine display end WINDOW rename display as window_display end feature ... end
Одна из ветвей наследования меняет имя display, а потому, по правилу дублируемого наследования BUTTON, будет иметь два варианта компонента. Один из них переопределен, но имеет прежнее имя; второй переопределен не был, но именуется теперь window_display.
Этот вариант кода почти корректен, однако в нем не хватает подвыражения select. Если, как это обычно бывает, мы хотим выбрать переопределенную версию, то запишем:
indexing note: "Это (корректная!)схема дублируемого наследования,% % использующая оригинальную версию переопределяемого компонента" class BUTTON inherit WINDOW redefine display select display end WINDOW rename display as window_display export {NONE} window_display end feature ...
end
Если такая схема должна применяться к целому ряду компонентов, их можно перечислить вместе. При этом нередко возникает необходимость разрешить все конфликты именно в пользу переопределенных компонентов. В этом случае можно воспользоваться select all.
Предложение export (см. лекцию 16) определяет статус экспорта наследуемых компонентов класса. Так, WINDOW может экспортировать компонент display, а BUTTON сделать window_display скрытым (поскольку его клиенты в нем не нуждаются). Экспорт исходной версии наследуемого компонента может сделать класс формально некорректным, если она не соответствует новому инварианту класса. |