Основы объектно-ориентированного программирования

         

Правило типизации


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

Вначале рассмотрим обычные, не родовые классы. Пусть C такой класс. Рассмотрим объявление его компонента, не использующее, естественно, никаких формальных родовых параметров:

f(a:T):U is ...

Тогда вызов вида x.f(d), появляющийся в произвольном классе B, где x типа C будет мудро корректен по типу, тогда и только тогда, когда:

  • f доступен классу B, - экспортирован всем классам или множеству классов, включающих B;
  • d принадлежит типу T. Если учитывать возможность наследования, то d может принадлежать потомкам T.
  • Результат вызова имеет тип U. В этом примере предполагается, что компонент f является функцией.

Теперь предположим, что C родовой класс с формальным родовым параметром G имеет компонент:

h (a: G): G is...

Вызов h имеет вид y.h(e), где y сущность, объявленная как

y: C [V]

Тип V - некоторый ранее определенный тип. Теперь правило типизации - двойник неродового правила - требует, чтобы e имело тип V или при наследовании было потомком V. Аналогичное требование к результату выполнения функции h.

Требования правила понятны: V - фактический параметр, заменяющий формальный родовой параметр G параметризованного класса C, поэтому он заменяет все вхождения G при вызове компонент класса. Все предыдущие примеры следовали этой модели: вызов s.put(z) требует параметра z типа POINT, если s типа STACK [POINT]; INTEGER если s типа STACK [INTEGER]; и s.item возвращает результат типа POINT в первом случае и типа INTEGER во втором.



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