Процедуры, связанные с типом
Глобально объявленные процедуры могут быть ассоциированы с типом запись, объявленным в том же самом модуле. В этом случае говорится, что процедуры связаны с типом запись. Связь выражается типом приемника в заголовке объявления процедуры. Приемник может быть или параметром-переменной типа Т, если Т - тип запись, или параметром-значением типа POINTER TO T (где T - тип запись). Процедура, связанная с типом T, рассматривается как локальная для него.
ЗаголовокПроцедуры | = | PROCEDURE [Приемник] ИдентОпр [ФормальныеПараметры]. |
Приемник | = | "(" [VAR] имя ":" имя ")". |
Если процедура P связана с типом T0, она неявно также связана с любым типом T1, который является расширением T0. Однако процедура P' (с тем же самым именем что и P) может быть явно связана с T1, перекрывая в этом случае связывание c P. P' рассматривается как переопределение P для T1. Формальные параметры P и P' должны совпадать (см. Прил. A). Если P и T1 экспортируются (см. Главу 4), P' также должна экспортироваться.
Если v - обозначение, а P - связанная процедура, то v.P обозначает процедуру P, связанную с динамическим типом v. Заметим, что это может быть процедура, отличная от той, что связана со статическим типом v. v передается приемнику процедуры P согласно правилам передачи параметров, определенным в Главе .
Если r - параметр-приемник, объявленный с типом T, r.P^ обозначает (переопределенную) процедуру P, связанную с базовым для T типом. В опережающем объявлении связанной процедуры и в фактическом объявлении процедуры параметр-приемник должен иметь одинаковый тип. Списки формальных параметров в обоих объявлениях должны быть идентичны.
Примеры:
PROCEDURE (t: Tree) Insert (node: Tree);
VAR p, father: Tree;
BEGIN p := t;
REPEAT father := p;
IF node.key = p.key THEN RETURN END;
IF node.key < p.key THEN p := p.left ELSE p := p.right END
UNTIL p = NIL;
IF node.key < father.key THEN father.left := node ELSE father.right := node END;
node.left := NIL; node.right := NIL
END Insert;
PROCEDURE (t: CenterTree) Insert (node: Tree); (*переопределение*)
BEGIN
WriteInt(node(CenterTree).width);
t.Insert^ (node) (* вызывает процедуру Insert, связанную с Tree *)
END Insert;