КАТЕГОРИИ: Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748) |
Использование исходной версии при переопределении
Обратного пути нет
Можно было бы ожидать, что допустимо и обратное переопределение атрибута в функцию без аргументов. Но нет. Присваивание - операция применимая к атрибутам, - становится бессмысленной для функций. Предположим, что a - это атрибут класса C, и некоторая подпрограмма содержит команду
a:= some_expression
Если потомок C переопределит a как функцию, то эта функция будет не применима, поскольку нельзя использовать функцию в левой части присваивания. Отсутствие симметрии (допустимо изменять объявление функции на объявление атрибута, но не наоборот) неприятно, но неизбежно и не является на практике серьезным препятствием. Оно означает, что объявление некоторого компонента атрибутом является окончательным и необратимым выбором, в то время как объявление его функцией все еще оставляет место для последующих реализаций через память, а не через вычисление.
Рассмотрим некоторый класс, который переопределяет подпрограмму, унаследованную от родителя. Обычная схема переопределения состоит в том, чтобы выполнить все, что делает исходная версия, предпослав ей или поместив за ней некоторые специальные действия. Например, класс BUTTON, наследник класса WINDOW, может переопределить компонент display, рисующий кнопку, так чтобы вначале рисовалось окно, а затем появлялась рамка:
class BUTTON inherit WINDOW redefine display end feature -- Вывод display is -- Изобразить как кнопку. do "Изобразить как нормальное окно"; -- См. ниже draw_border end ... Другие компоненты... end
где draw_border - это процедура нового класса. Для того чтобы "Изобразить как нормальное окно", нужно вызвать исходную версию display, технически известную как precursor (предшественник) процедуры draw_border. Это достаточно общий случай, и желательно ввести для него специальное обозначение. Конструкцию
Precursor
можно использовать в качестве имени компонента, но только в теле переопределяемой подпрограммы. Вызов этого компонента, если нужно с аргументами, является вызовом родительской версии этой процедуры (предшественника). Поэтому в последнем примере часть "Изобразить как нормальное окно" можно записать просто как
Precursor
Это будет означать вызов исходной версии этой процедуры из класса WINDOW, допустимый при переопределении процедуры классом-наследником WINDOW. Precursor - это зарезервированное имя сущности такое же, как Result или Current, и оно так же пишется курсивом с заглавной первой буквой. В данном примере переопределяемый компонент является процедурой и поэтому вызов конструкции Precursor - это команда. Этот же вызов может участвовать при переопределении функции в выражении:
some_query (n: INTEGER): INTEGER is -- Значение, возвращаемое версией родителя, если оно -- положительно, иначе ноль do Result:= (Precursor (n)).max (0) end
В случае множественного наследования, рассматриваемого в следующей лекции, у процедуры может быть несколько предшественников, что позволяет объединить несколько наследуемых процедур в одну. Тогда для устранения неоднозначности нужно будет указывать родителя, например, Precursor WINDOW. Заметим, что использование конструкции Precursor не делает компонент-предшественник компонентом данного класса, компонентом является только его переопределенная версия. (В частности, предшествующая версия может не удовлетворять новому инварианту.) Целью конструкции является облегчение переопределения в случае, когда новая версия включает старую.
В более сложном случае, когда, в частности, требуется использовать и предшествующую и новую версии в качестве компонентов класса, можно воспользоваться дублируемым наследованием, при котором родительский компонент, фактически, дублируется, и у наследника создаются два законченных компонента. Это будет подробно обсуждаться при рассмотрении дублируемого наследования.
Дата добавления: 2014-01-07; Просмотров: 251; Нарушение авторских прав?; Мы поможем в написании вашей работы! Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет |