Ада-95. Компилятор GNAT

       

Динамическая передиспетчеризация


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

В случае использования классов, необходимо заботиться в правильном распознавании вызова реализации для потомка от вызова реализации для предка.

Рассмотрим следующий схематический вариант реализации процедуры Display для типа Root:

procedure Display (Self: in Root) is

begin

Put ( The_Name(Self) & ... ); -- ??? . . . end Display;

В данном случае, при вызове реализации Display для типа Child_1, которая была показана ранее, первая же инструкция выполняет вызов затененной реализации предка, то есть, реализации для типа Root: Display ( Root(Self) ).

Показанный пример реализации процедуры Display для типа Root

всегда будет выполнять вызов функции The_Name полагая, что индивидуальным типом параметра Self является тип Root.

Таким образом, этот вызов будет статически связан с реализацией функции The_Name для типа Root.

Следовательно, при вызове реализации процедуры Display для типа Child_1, в результате вызова затененной реализации предка будет получена та же строка имени, что и для типа Root.

Для того, чтобы процедура Display для типа Root

правильно осуществила вызов той реализации функции The_Name

которая соответствует фактическому индивидуальному типу параметра Self

ее необходимо переписать следующим образом:

procedure Display (Self: in Root) is

begin

Put ( The_Name( Root'Class(Self) ) & ... ); -- передиспетчеризация . . . end Display;

В данном случае, в реализации процедуры Display для типа Root

выполняется преобразование параметра Self

к типу Root'Class предусматривая передиспетчеризацию вызова к корректной реализации The_Name, в зависимости от тэга параметра Self.



Содержание раздела