| PrintObj( ObjStringVar );

| PrintObj( ObjSymVar );

| END.

Рис. 13.6

- 281 -

Обращаем внимание на легкость реализации процедуры. Она не зависит от процессов внутри объектов, а только вызывает нужный нам метод обработки полей данных (разнотипных). Поскольку мы предварительно сами позаботились о том, чтобы у всех наших объектов был одинаковый по написанию метод Print, его запись в процедуре встречается один раз. Но здесь необходимо сделать оговорку. Несмотря на внешнюю правильность примера, он будет работать не совсем корректно: всегда будет срабатывать метод Print для типа объекта ObjPos, независимо от типа фактического параметра. Это происходит потому, что во всех объявленных выше объектах используются статические методы.

<p>13.5.1. Статические методы</p>

Такое название методов связано с тем, что размещение соответствующих ссылок на них осуществляется еще на этапе компиляции.

Обработка компилятором статических методов похожа на обработку статических переменных. Действия компилятора при обработке методов объектов, составляющих некую иерархию, таковы:

1. При вызове метода компилятор устанавливает тип объекта, вызывающего метод.

2. Установив тип, компилятор ищет метод в пределах типа объекта. Найдя его, компилятор назначает вызов этого метода.

3. Если указанный метод не найден, то компилятор начинает рассматривать тип непосредственного прародителя и ищет метод, имя которого вызвано, в пределах этого прародительского типа. В случае, если метод с таким именем найден, вызов заменяется на вызов метода прародителя.

4. Если же искомый метод отсутствует в типе ближайшего прародителя, то компилятор переходит к типу следующего прародителя («дедушке») нашего типа, где и осуществляет дальнейший поиск. Процесс продолжается до тех пор, пока вызванный метод не будет найден, иначе компилятор, дойдя до самого последнего типа («родоначальника») и не найдя метод, имя которого вызывается, выдаст сообщение об ошибке компиляции номер 44 Field identifier expected («Ожидается идентификатор поля»). Это говорит о том, что метод с таким именем не определен.

Из всего этого следует одна важная особенность. Если метод прародителя вызывает другие методы, то последние также будут методами прародителя, даже если потомки имеют свои собственные методы.

- 282 -

Применительно к примеру на рис. 13.6 сработают правила 1 и 2, и будет выполнен метод, объявленный в типе формального параметра (т.е. ObjPos.Print). Для того чтобы процедура заработала правильно, необходимо объявить метод Print виртуальным.

<p>13.5.2. Виртуальные методы</p>

13.5.2.1. Виртуализация методов. Из правил совместимости фактических и формальных параметров типа «объект» следует, что в качестве фактического параметра может выступать объект любого производного типа от типа формального параметра. Таким образом, во время компиляции процедуры неизвестно, объект какого типа будет ей передан в качестве фактического параметра (такой параметр называется полиморфным объектом). В полной мере полиморфизм объектов и методов реализуется при помощи виртуальных методов.

Метод становится виртуальным, когда за его определением в типе объекта ставится служебное слово VIRTUAL:

PROCEDURE ИмяМетода( параметры ); VIRTUAL;

или

FUNCTION ИмяМетода( параметры ) : ТипЗначения; VIRTUAL;

При виртуализации методов должны выполняться следующие условия:

1. Если прародительский тип объекта описывает метод как виртуальный, то все его производные типы, которые реализуют метод с тем же именем, должны описать этот метод тоже как виртуальный. Другими словами, нельзя заменять виртуальный метод статическим. Если же это произойдет, компилятор сообщит об ошибке номер 149 VIRTUAL expected («Ожидается служебное слою VIRTUAL»).

2. Если переопределяется реализация виртуального метода, то заголовок заново определяемого виртуального метода в производном типе не может быть изменен. Иначе говоря, должны остаться неизменными порядок расположения, количество и типы формальных параметров в одноименных виртуальных методах. Если этот метод реализуется функцией, то не должен изменяться и тип результата. При изменении заголовка метода компилятор выдаст сообщение об ошибке номер 131 Header does not match previous definition («Заголовок не соответствует предыдущему определению»).

- 283 -

Перейти на страницу:

Поиск

Похожие книги