Динамическая передиспетчеризация
Известно, что производный тип всегда может переопределить примитивную операцию своего предка, то есть, предусмотреть свою собственную реализацию примитивной операции.
В случае использования классов, необходимо заботиться в правильном распознавании вызова реализации для потомка от вызова реализации для предка.
Рассмотрим следующий схематический вариант реализации процедуры 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.