Справочник Ada 2005
10.1.2 Пункты контекста — пункты With
Пункт context_clause используется для указания элементов_библиотеки, имена которых необходимы в единице компиляции.
Синтаксис
limited_with_clause ::= limited [private] with имя_единицы_библиотекиname {, имя_единицы_библиотекиname};
nonlimited_with_clause ::= [private] with имя_единицы_библиотекиname {, имя_единицы_библиотекиname};
Правила разрешения имен
Область видимости with_clause, который появляется в объявлении_единицы_библиотеки или переименовании_объявления_единицы_библиотеки, включает весь декларативный регион объявления, включая все дочерние элементы и подмодули. Область видимости with_clause, который появляется в теле, включает тело, включая все подмодули.
Элемент_библиотеки (и соответствующая единица библиотеки) называется в with_clause, если он обозначен с помощью имя_единицы_библиотеки в with_clause. Элемент_библиотеки (и соответствующая единица библиотеки) указан в with_clause, если он называется в with_clause или если он обозначен с помощью префикса в with_clause.
За пределами собственного декларативного региона объявление или переименование единицы библиотеки может быть видимым только в пределах области видимости with_clause, который его упоминает. Видимость объявления или переименования единицы библиотеки в противном случае следует из его расположения в среде.
Правила законности
Если with_clause данной единицы_компиляции упоминает частного потомка некоторой единицы библиотеки, то данная единица_компиляции должна быть одной из следующих:
- объявление, тело или подмодуль частного потомка этой единицы библиотеки;
- тело или подмодуль публичного потомка этой единицы библиотеки, но не тело подпрограммы, выполняющей роль объявления подпрограммы (см. 10.1.4); или
- объявление публичного потомка этой единицы библиотеки, в этом случае with_clause должен включать зарезервированное слово private.
Имя, обозначающее элемент библиотеки, видимый только из-за упоминания в одном или нескольких with_clause, включающих зарезервированное слово private, должно появляться только в:
- частной части;
- теле, но не в спецификации_подпрограммы тела подпрограммы библиотеки;
- частном потомке единицы, в которой один из этих with_clauses появляется; или
- pragma в рамках пункта контекста.
Элемент_библиотеки, упомянутый в limited_with_clause, должен быть неявным объявлением ограниченного представления пакета библиотеки, а не объявлением подпрограммы, обобщённой единицы, экземпляра обобщённой единицы или переименования.
Пункт limited_with_clause не должен появляться в теле_единицы_библиотеки, подмодуле или переименовании_объявления_единицы_библиотеки.
Пункт limited_with_clause, который называет пакет библиотеки, не должен появляться:
- в пункте context_clause для явного объявления названного пакета библиотеки;
- в одном и том же пункте context_clause с, или в области видимости, nonlimited_with_clause, упоминающим тот же пакет библиотеки; или
- в одном и том же пункте context_clause с, или в области видимости, use_clause, который называет сущность, объявленную в декларативной области пакета библиотеки.
ПРИМЕЧАНИЯ
3 Элемент_библиотеки, упомянутый в nonlimited_with_clause единицы компиляции, виден в пределах единицы компиляции и, следовательно, действует как обычное объявление. Таким образом, в рамках единицы компиляции, которая упоминает его объявление, имя пакета библиотеки может быть указано в use_clause, может быть использовано для формирования расширенных имён, подпрограмма библиотеки может быть вызвана, и экземпляры обобщённой единицы библиотеки могут быть объявлены. Если дочерний элемент родительского обобщённого пакета упоминается в nonlimited_with_clause, то соответствующее объявление, вложенное в каждый видимый экземпляр, видно в пределах единицы компиляции. Аналогично, Элемент_библиотеки, упомянутый в limited_with_clause единицы компиляции, виден в пределах единицы компиляции и, следовательно, может быть использован для формирования расширенных имён.
Примеры
package Office is
end Office;
end Office;
with Ada.Strings.Unbounded;
package Office.Locations is
type Location is new Ada.Strings.Unbounded.Unbounded_String;
end Office.Locations;
package Office.Locations is
type Location is new Ada.Strings.Unbounded.Unbounded_String;
end Office.Locations;
limited with Office.Departments; -- типы неполны
private with Office.Locations; -- виден только в частной части
package Office.Employees is
type Employee is private;
private with Office.Locations; -- виден только в частной части
package Office.Employees is
type Employee is private;
function Dept_Of(Emp : Employee) return access Departments.Department;
procedure Assign_Dept(Emp : in out Employee;
Dept : access Departments.Department);
procedure Assign_Dept(Emp : in out Employee;
Dept : access Departments.Department);
...
private
type Employee is
record
Dept : access Departments.Department;
Loc : Locations.Location;
...
end record;
end Office.Employees;
private
type Employee is
record
Dept : access Departments.Department;
Loc : Locations.Location;
...
end record;
end Office.Employees;
limited with Office.Employees;
package Office.Departments is
type Department is private;
package Office.Departments is
type Department is private;
function Manager_Of(Dept : Department) return access Employees.Employee;
procedure Assign_Manager(Dept : in out Department;
Mgr : access Employees.Employee);
...
end Office.Departments;
procedure Assign_Manager(Dept : in out Department;
Mgr : access Employees.Employee);
...
end Office.Departments;
Пункт limited_with_clause может быть использован для поддержки взаимно зависимых абстракций, которые разделены на несколько пакетов. В этом случае сотрудник назначается в отдел, а отдел имеет руководителя, который является сотрудником. Если with_clause со словом private появляется в одной единице библиотеки и упоминает вторую единицу библиотеки, это обеспечивает видимость второй единицы библиотеки, но ограничивает эту видимость частной частью и телом первой единицы. Компилятор проверяет, что вторая единица не используется во видимой части первой единицы.