Мир программирования

 


Найти: на:


Меню
Партнеры
Счетчики
Реклама

Наследуемые статические методы


 Предыдущая страница     |     Следующая страница  
Добавить в избанное Обсудить в форуме Написать автору сайта

         Один из  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 программирование: Бурлаков Михаил

Используются технологии uCoz