На странице 324 «Программирование в Ada 2012» Джона Барнса он заявляет, что неопределенный вызов тега будет компилироваться, если существует только один тип, определяющий задействованные примитивы. Итак, учитывая:
root.ads:
package root is
type object is tagged null record;
function is_further (X, Y: Object) return boolean;
function unit return object;
-- type circle is new object with null record;
end root;
Вызов is_further(unit, unit)
скомпилируется. Однако, если мы позже добавим производный тип, такой как окружность, к этому интерфейсу, вызов будет неоднозначным:
main.adb:8:14: ambiguous expression (cannot resolve "is_further")
main.adb:8:14: possible interpretation (inherited) at other.ads:4
main.adb:8:14: possible interpretation at root.ads:5
main.adb:8:25: ambiguous call to "unit"
main.adb:8:25: interpretation at other.ads:4
main.adb:8:25: interpretation at root.ads:6
gprbuild: *** compilation phase failed
Насколько я знаю, это делает Ada единственным языком программирования, где добавление производного типа является изменение интерфейса ломается. Поскольку это ужасная перспектива, есть ли способ заставить данное выражение всегда терпеть неудачу, даже с одним типом?
Неуклюжим решением является определение частного производного типа, который не используется, для каждого листа (под) тип, который я выставляю. (хотя я не могу заставить клиентов не использовать его, позже я не буду расширять этот тип, поэтому проблема не возникнет)
Обратите внимание, что проблема не только в root тип. Это проблема для всех типов листа (т.е. без какого-либо производного от него типа). Например, если мы позже расширим объект в другом пакете:
with root; use root;
package circles is
type round_thing is new object with null record;
procedure turn_around( R : round_thing );
type ambiguate_indeterminate_calls_for_round_thing is new round_thing with null record;
end circles;
Я на самом деле хотел просто определить round_thing и оставить возможность позже добавить овал. Но без неиспользуемого производного типа кто-то мог бы написать turn_around(unit)
в то же время, поэтому, когда я добавлю свой овальный тип, он столкнется с ambiguous expression (cannot resolve "turn_around")
.
Мне кажется, что в Аде есть недостаток, заключающийся в том, что разрешены неопределенные вызовы тегов, поэтому есть ли хороший способ запретить их, либо изменив код в пакете, либо добавив флаг компилятора?