Comdiv писал(а):
Comdiv писал(а):
Процедурные типы - это единственное средство, опирающееся на структурную, а не именную совместимость по типам.
Не совсем точно, потому что в Oberon структурная совместимость также у открытых массивов, допустимых в формальных параметрах, а в Компонентном Паскале и для указателей:
Цитата:
Правила совместимости для указателей были ослаблены и упрощены. Теперь указатели совместимы по структуре; то есть два указательных типа, имеющих общий базовый тип, являются совместимыми. Это может быть полезно в основном в сигнатурах процедур, где раньше было невозможно использовать функции, подобные следующей:
PROCEDURE P (p: POINTER TO ARRAY OF INTEGER)
Тогда, пожалуй, и типы-синонимы тоже - структурно, а не номинально совместимы:
Код:
TYPE Color = INTEGER;
VAR col: Color; w: INTEGER;
BEGIN
col := 7; col := w;
Синонимы позволяют сделать замысел программиста более явным, и потому программу - понятнее.
Из-за структурной совместимости они не добавляют проверок.
И из-за структурной совместимости ими удобно пользоваться - иначе пришлось бы приводить 7 и w к типу Color.
А что если определить правила совместимости иначе: синоним и его базовый тип совместимы, но требуется явное приведение между синонимами одного базового типа?
Код:
TYPE
Pixels = INTEGER;
Units = INTEGER;
(* Pixels и INTEGER совместимы, Units и INTEGER совместимы, Pixels и Units несовместимы, требуют явного приведения *)
PROCEDURE (rd: Rider) DrawRect (l, t, r, b: Pixels);
PROCEDURE (f: Frame) DrawRect (l, t, r, b: Units);
PROCEDURE P (f: Frame; rd; Rider; x, y: Units);
BEGIN
f.DrawRect(0, 0, x, y);
rd.DrawRect(0, 0, x DIV f.unit, y DIV f.unit);
rd.DrawRect(0, 0, x, y) (* недопустимо, ошибка компиляции *)
END P;
Это бы позволило компилятору проводить дополнительные проверки и обращать внимание на потенциальные ошибки, в данном примере - ошибку масштабирования координат.