|
|||||||||||||||||||
|
Наследуемые статические методыОдин из Point методов перекрывается методом MoveTo в определении типа Circle. Если Вы внимательны, то посмотрев на MoveTo, Вы можете удивиться, почему MoveTo не использует поле Radius и не делает вызова BGI или других библиотек для изображения окружностей. В то же время GetX и GetY методы наследуются на протяжении всего пути из InitLocation без изменений. Также, Circle. MoveTo полностью идентичен Point.MoveTo. Ничего не изменилось, произошло только копирование программы и перед идентификатором MoveTo появился квалификатор Circle. Этот пример демонстрирует проблему с объектами и методами, появляющуюся при работе в таком стиле. Все методы, показанные в связи с Location, Point и Circle типами объектов, являются статическими методами. (Термин "статические" был выбран для того, чтобы описать метод, не являющийся виртуальным, термин, который мы скоро введем. Виртуальные методы фактически являются решением этой проблемы, но для того, чтобы понять решение, Вам нужно вначале понять саму проблему). Симптомы этой проблемы таковы: до тех пор, пока копия MoveTo метода не будет помещена в сфере действия Circle для того, чтобы перекрыть Point.MoveTo, метод будет работать неправильно при вызове из объекта типа Circle. Если Circle вызывает Point.MoveTo метод, то на экране будет передвигаться скорее точка, а не окружность. Только когда Circle вызовет копию MoveTo метода, заданного в своей сфере действия, то окружности будут удаляться и рисоваться путем вложенных вызовов Show и Hide. Почему так? Это было сделано в соответствии со способом, которым компилятор решает вызовы методов. Когда компилятор компилирует Point методы, он сначала наталкивается на Point.Show и Point.Hide и компилирует коды для них обоих в сегмент кода. Немного ниже в файле он встречает Point.MoveTo, который вызывает Point.Show и Point.Hide. Как и при вызове любой процедуры, компилятор заменяет исходный код, ссылающийся на Point.Show и Point.Hide, адресами сгенерированного кода в сегменте кода. Таким образом, когда вызывается код для Point.MoveTo, он вызывает код для Point.Show и Point.Hide и все в порядке. Этот сценарий является классикой Turbo Pascal и поддерживается (кроме терминологии) с версии 1.0. Однако с появлением наследования все меняется. Когда Circle наследует метод от Point, Circle использует метод точно так, как он был откомпилирован. Посмотрим опять, что будет унаследовано Circle, если он унаследовал Point.MoveTo: procedure Point.MoveTo(NewX, NewY : Integer); begin Hide; {вызывает Point.Hide} X := NewX; Y := NewY; Show; {вызывает point.Show} end; Комментарии были добавлены для того, чтобы подчеркнуть факт, что когда Circle вызывает Point.MoveTo, он так же вызывает Point.Show и Point.Hide, а не Circle.Show и Circle.Hide. Point.Show рисует точку, а не окружность. Поскольку Point.MoveTo вызывает Point.Show и Point.Hide, Point.MoveTo не может быть наследован. Вместо этого он должен быть заменен второй копией самого себя, которая вызывает Show и Hide, определенные внутри своей сферы действия; т.е., Circle.Show и Circle.Hide. Логика компилятора в решении вызовов методов работает следующим образом: при вызове метода компилятор вначале ищет метод с этим именем, определенный внутри типа объект. Circle тип определяет методы, названные Init, Show, Hide, Expand, Contract и MoveTo. Если будет вызов одного из этих пяти методов Circle, то компилятор заменит вызов адресом одного из собственных Circle методов. Если метод с таким именем не определен внутри типа объект, то компилятор обращается к непосредственному родительскому типу и ищет внутри этого типа метод с таким именем. Если метод с этим именем найден, то адрес родительского метода заменяет имя в исходном коде метода потомка. Если метод с данным именем не найден, то компилятор поднимается выше к следующему предку в поисках названного метода. Если компилятор достиг самого первого типа объект (верхушки), то он выдаст сообщение об ошибке, указывающее, что этот метод неопределен. Но когда статический наследуемый метод найден и используется, Вы должны помнить, что вызванный метод - это метод точно такой, как он определен и откомпилирован для родительского типа. Если родительский метод вызывает другие методы, то вызываемые методы будут родительскими методами, даже если потомок имеет методы, которые отвергают родительские методы. Предыдущая страница | Следующая страница |
|
Web дизайн: Бурлаков Михаил
Web программирование: Бурлаков Михаил