Rationale for Ada 2005: Structure and visibility
RUSTOPBACKNEXT
ENG |
2. Mutually dependent types
@ For many programmers the solution of the problem of mutually dependent types will be the single most important improvement introduced in Ada 2005. @ This topic was discussed in the Introduction using an example of two mutually dependent types, Point and Line. Each type needed to refer to the other in its declaration and of course the solution to this problem is to use incomplete types. In Ada 95 there are three stages. We first declare the incomplete types
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Rationale for Ada 2005: Structure and visibility
@ENGRUSTOPBACKNEXT2. Взаимно-зависимые типы
@ Для многих программистов решение проблемы взаимно зависимых типов будет одним из самых важных усовершенствований, введенным в Аде 2005.
@ Эта тема обсуждалась во Введении при обсуждении примера о двух взаимно зависимых типах Point и Line. Там каждый тип ссылался на другой при объявлении. Решение этой проблемы состоит в том, чтобы использовать неполные определения типов. В Аде 95 это делается в три шага. Сначала мы объявляем неполные типы:
|
@ Пусть каждая точка ассоциируется с тремя линиями проходящии через неё, а каждая линия ассоциируется с тремя точками через которые она проходит. (Это не настолько глупо. Две самых фундаментальных теоремы проективной геометрии, такие как Pappus и Desargues касаются таких структур, и их используют самые простые из конечных геометрий, поверхность Fano.)
@ Далее мы определяем ссылочные типы на неполные типы:
|
@ и только теперь получаем окончательный результат:
|
@ В Аде 2005, как обсуждалось в предыдущей статье, мы можем использовать анонимные ссылочные типы более свободно и можем опустить второй шаг в этом примере. Таким образом, полные объявления будут:
|
@ Это даёт важное преимущество, т.к. мы избавлены от необходимости изобретать раздражающие идентификаторы, типа Point_Ptr.
@ Но в настоящий момент мы будем придерживаться ada в которой имеется два правила: 1) неполный тип может использоваться только для определения ссылочных типов; и 2) полное объявление типа должно быть в той же самой декларативной области где и неполный тип.
@ Первое правило фактически разрешает:
|
@ Отметим, что мы здесь используем неполный тип T в качестве параметра процедуры. Это обычно не позволяется, но в данном случае определяется не сама процедура а ссылочный тип на неё. Это задаёт дополнительный уровень косвенности для параметра T который на данном этапе не известен, и пока не имеет значения.
@ Кроме этого, нельзя использовать неполный тип в качестве параметра в подпрограмме на Аде 95 кроме как в ссылочном параметре. Таким образом, мы не можем написать:
|
@ перед полными объявлениями типа.
@ Стоит упомянуть, что проблема взаимно зависимых типов (в пределах единственного модуля) может решаться использованием частных типов так:
|
@ Но мы должны использовать неполные типы, если хотим, чтобы пользователь видел полное представление типа, таким образом, ситуация несколько отличается.
@ Как в стороне, помните, что, если неполный тип объявлен в частной секции тогда, полный тип может быть задержан к телу (это - так называемая Поправка Taft в Аде 83). В этом случае ни пользователь, ни действительно компилятор не может видеть полный тип, и это - основная причина, почему мы не можем иметь параметры неполных типов, тогда как мы можем это для частных типов.
@ Рссмотрим канонический пример иллюстрирующий эту тему. Пусть имеется некая организация состоящая из отделов в которых работают служащие. Информация о служащих должна обратиться к отделам, и отделы должны обратиться к служащим. Мы предполагаем, что материал относительно служащих и отделов является весьма большим так, чтобы мы естественно желали объявить два типа в отличных пакетах Employees и Department. Попытка определить это следующим образом:
|
@ не корректна, потому что каждый пакет имеет with-утверждение с ссылкой на другой, и они не могут оба быть объявлены (или введены из библиотеки) сначала.
@ Мы предполагаем конечно, что тип Employee включает информацию об Department в котором работает Employee, и тип Department содержит информацию относительно менеджера отдела, и по-видимому список других служащих также - отметим, что менеджер - естественно также Employee (Служащий).
@ Так в Аде 95 мы вынуждены поместить всё в один пакет:
|
@ Мало того, что это дает начало огромным громоздким пакетам, но и это также препятствует нам использовать надлежащие абстракции. Таким образом, типы Employee (Служащий) и Department (Отдел) должны быть объявлены в той же самой частной секции и не защищены от операций друг друга.
@ Ада 2005 решает эту проблему, вводя разновидность with утверждения - limited with утверждение. Такое утверждение дает возможность модулю библиотеки иметь неполное представление всех видимых типов в другом пакете. Теперь мы можем написать:
|
@ Важно понять, что утверждение limited with не налагает зависимость. Таким образом, если пакет A имеет limited with для B, то A не зависит от B как при нормальном with утверждении, и таким образом, B не должен быть собран прежде A или помещен в библиотеку прежде A.
@ Если мы имеем цикл пакетов, мы только должны поместить limited with утверждение в один пакет, и этого достаточно, чтобы нарушить цикл зависимостей. Однако, для симметрии, в этом примере мы заставили их обоих иметь ограниченное представление друг друга.
@ Отметим терминологию: мы говорим, что мы имеем ограниченное представление пакета, если представление обеспечивается через limited with утверждение. Таким образом, ограниченное представление пакета обеспечивает неполное представление его видимых типов. И неполным представлением мы подразумеваем, как будто они были неполными типами.
@ В примере, потому что неполное представление типа не может вообще использоваться как параметр, мы должны были изменить один параметр каждого из Assign_Employee и Choose_Manager, чтобы быть ссылочным параметром.
@ Есть множество правил, необходимых для того чтобы избежать проблем. Одно из них состоит в том, что мы не можем иметь и limited with утверждение и нормальное with утверждение для одного и того же пакета в одном и том же контекстном пункте (нормальное with утверждение теперь официально упоминается как неограниченное with утверждение). Важное и, возможно, неожиданное правило состоит в том, что мы не можем иметь use утверждение пакета с ограниченным представлением, потому что при этом могут случиться серьезные неожиданности.
@ Т.о. важно понять, что limited with утвверждение обеспечивает очень ограниченное представление пакета. Оно делает видимым только название пакета и пакетов, вложенных в пределах неполного представления типов, объявленных в видимых частях пакетов.
@ Ничто иное не видимо вообще. Теперь рассмотрим:
|
@ В пределах пакета P мы не можем обратиться ни к A.X ни к B.X, потому это объекты а не типы. Но мы могли бы объявить дочерний пакет с его собственным with выражением следующим образом:
|
@ Неограниченное with утверждение на ребенке "отменяет" limited with утверждение на родителе так, что A.X стал видим.
@ Теперь предположим, что нам разрешали добавить пакетное use утверждение к родительскому пакету; так как use утверждение на родителе обращается к ребенку, это означает, что мы могли обратиться к A.X когда X в пределах ребенка, таким образом мы будем иметь:
|
@ Если мы должны были теперь изменить with утверждение на ребенке, чтобы обратиться к B вместо A, то X обратится к B.X, а не A.X. Это не было бы вообще очевидно, потому что use утверждение, которое разрешает это, находится на родителе, и мы не изменяем контекстный пункт родителя вообще. Ясно что это было бы недопустимым и, таким образом, пакетное use утверждения запрещаются, если мы имеем только ограниченное представление пакета.
@ Вот полный список правил, проектирования, чтобы предотвратить несчастный случай когда использование limited with утверждений, пакетных use утверждений не может обратиться к пакету с ограниченным представлением как проиллюстрировано выше:
|
@ правило также предотвращает:
|
@ - limited with утверждение может только появиться в спецификации - оно не может появиться в теле или субмодуле
|
@ - limited with утверждение и неограниченное with утверждение для того же самого пакета не может появляется в том же самом контекстном пункте,
|
@ - limited with утверждение и use утверждение для того же самого пакета или одного из его потомков, не может появляется в том же самом контекстном пункте,
|
@ - limited with утверждение не может появляется в контекстном пункте, обращающемся к себе,
|
@ - limited with утверждение, не может появляется в дочернем модуле, если неограниченный with для того же самого пакета обращается к его родителю или прародителю и т.д,
|
@ но заметим, что обратное разрешено
|
@ - limited with утверждение не может появляется в пределах пункта использования, который называет модуль или одного из его потомков,
|
@ без этого определенного правила, use утверждение в Q, которое фактически обращается к A, столкнулся бы с limited with утверждением для A.
@ Наконец отметим, что limited with утверждение может только обратиться к объявлению пакета а не к подпрограмме, родовому объявлению или реализации, или к переименовывающему пакету.
@ Возвратимся теперь к правилам для неполных типов. Как было упомянуто выше правила для неполных типов весьма строги в Аде 95, и кроме любопытного случая ссылки к типу подпрограммы не возможно использовать неполный тип в качестве параметра кроме как в ссылочном параметре.
@ Ада 2005 допускает некоторое послабление этих правил, вводя теговые неполные типы. Мы можем написать:
|
@ и тогда полный тип должен быть тэговым типом. Конечно обратное не допустимо. Если мы имеем только
|
@ тогда законченный тип T мог бы быть теговым или нет.
@ Любопытная особенность ada была упомянута во Введении. В Аде 95 мы можем написать:
|
@ При использовании атрибута Class это обещает довольно хитрым способом, которым будет отмечен законченный тип T. Это является анахронизмом в Аде 2005 и перемещено в Приложение J. В Аде 2005 мы должны написать:
|
@ Большое преимущество представления теговых неполных типов состоит в том, что мы знаем, что с теговыми типами всегда передается справочная информация и, таким образом, нам разрешается использовать теговые неполные типы в качестве параметров.
@ Это преимущество простирается на неполное представление, полученное из limited with выражения. Если тип в пакете явно теговый тогда, неполное полученное представление неполное теговое и таким образом тип может использоваться для параметров.
@ Возвращаясь к пакетам Employess и Departments, вероятно имеет смысл сделать оба типа теговыми, так как вероятно, что типы Employee (Служащий) и Department (Отдел) формируют иерархию. Таким образом, мы можем написать:
|
@ Текст является неcколько громоздким теперь with Классом, опрыснутым подробно вокруг, но мы можем ввести некоторые подтипы, чтобы сократить названия. Мы можем также избежать введения типа Dept_Ptr, так как мы можем использовать анонимный ссылочный тип для функционального результата упомянуто в предыдущей статье. Таким образом мы имеем:
|
@ Заметим, что в Аде 2005 мы можем использовать простой подтип как сокращение для неполного типа таким образом:
|
@ но у такого подтипа не может быть ограничения или нулевого исключения. В основном это - только переименовывание.
@ Помните, что у нас не может быть use выражения с ограниченным представлением. Кроме того, много проектов запрещают use выражения так или иначе, но разрешают переименования и подтипы для местных сокращений. Это создавало бы большие трудности, если бы такие сокращения не были также доступны при помощи limited with выражений.
@ Жаль, что мы не можем также написать:
|
@ но тогда у Вас не может быть всего в жизни.
@ Подобная ситуация возникает с названиями вложенных пакетов. Они могут быть переименованы, чтобы обеспечить сокращение.
@ Механизм для того, чтобы ломать циклы зависимостей, вводя limited with выражения не означает, что реализация не проверяет все полностью в строгой Аде путь. Это только, что некоторые проверки, возможно, придется задержать. Детали зависят от реализации.
@ Для человеческого читателя это очень полезно, которые используют выражения, не позволены вместе с ограниченным с выражениями, так как это устраняет любое сомнение относительно местоположения вовлеченных типов. Это вероятно помогает плохим компиляторам также.
@ Читатели могли бы заинтересоваться, чтобы знать, что эта тема была одним из самых трудных, чтобы решить удовлетворительно в дизайне Ады 2005. В целом семь различных версий искусственного интеллекта 217 были разработаны. Это выбранное решение находится на отражении безусловно лучшее и было фактически номер 6.
@ Многие обходы цикла в Аде 95 относительно неполных типов также закрыты в Аде 2005.
@ Один такой обход цикла иллюстрирован следующим (это - Ада 95)
|
@ Неполный тип T объявлен в частной части пакета P. Ссылочный тип ACT тогда объявлен и так как это - класс, широкий, это подразумевает, что тип T должен быть теговый (читатель знает из обсуждения выше об этой особенности, помещён в Приложение J в Аде 2005). Полный тип T тогда объявлен в теле. Мы также объявляем примитивную операцию Op типа T в частной части.
@ Однако, прежде, чем тело P будет объявлено, ничто в Аде 95 не препятствует тому, чтобы мы написали частному потомку таким образом:
|
@ и процедура Naughty может вызвать операцию Op диспетчеризации. Проблема состоит в том, что мы обязаны компилировать этот запрос прежде, чем тип T будет закончен и таким образом прежде, чем местоположение его тэга будет известно.
@
@ Эта проблема предотвращена в Аде 2005 по правилу, что, если у неполного типа, объявленного в частной части, есть примитивные операции тогда, завершение не может быть задержано к телу.
@
@ Подобные проблемы возникают со ссылками к типам подпрограммы. Таким образом, как упомянуто выше, Ада 95 пропусков
|
@ В Аде 2005 завершение T не может быть задержано к телу. И при этом мы не можем объявить такуюссылку к типу подпрограммы, если у нас только есть неполное представление T, вляющегося результатом limited with выражение.
@ Другое изменение в Аде 2005 может быть иллюстрировано примером Отделов и Служащих. Мы можем написать:
|
@ В Аде 95 есть правило, которое говорит, что "Вы не должны разыменовывать неполный тип". Это предотвратило бы запрос Assign_Employee, который ясно безопасен. Было бы странным потребовать, чтобы у Новичка был неограниченный with- выражением для Отделов, чтобы позволить запрос Assign_Employee. Соответственно правило изменено в Аде 2005 так, чтобы разыменование неполного представления было только запрещено когда используется как префикс как, например, в D'Size.
2010-10-24 00:26:54
. .