Spec-Zone.ru › Ada 2022
Руководство по Ada (Ada 2022)

7.3.1 Закрытые операции

Для типа, объявленного в видимой части пакета или обобщенного пакета, некоторые операции над типом становятся видимыми только позднее в пакете — либо в закрытой части, либо в теле. Такие закрытые операции доступны только внутри области объявления пакета или обобщенного пакета.

Статическая семантика

Предопределенные операторы, существующие для данного типа, определяются классами, к которым принадлежит тип. Например, целочисленный тип имеет предопределенный оператор "+". В большинстве случаев предопределенные операторы типа объявляются непосредственно после определения типа; исключения объяснены ниже. Наследуемые подпрограммы также неявно объявляются непосредственно после определения типа, за исключением случаев, указанных ниже.
Для составного типа характеристики (см. 7.3) типа частично определяются характеристиками его компонентов. В месте объявления составного типа используются только те характеристики типов компонентов, которые видимы в этом месте. Если позднее, непосредственно внутри области объявления составного типа, дополнительные характеристики становятся видимыми для типа компонента, то соответствующие характеристики становятся видимыми для составного типа. Любые дополнительные предопределенные операторы неявно объявляются в этом месте. Если такого места нет, то дополнительные предопределенные операторы не объявляются вообще, но они все равно существуют.
Соответствующее правило применяется к типу, определенному с помощью derived_type_definition, если существует место непосредственно внутри области объявления типа, где дополнительные характеристики его родительского типа становятся видимыми.
Например, тип массива, тип компонента которого является ограниченно закрытым, становится неограниченным, если полное представление типа компонента является неограниченным и видимым в некотором более позднем месте непосредственно внутри области объявления типа массива. В таком случае предопределенный оператор "=" неявно объявляется в этом месте, и присваивание разрешается после этого места.
Характеристики и ограничения обозначенного подтипа типа доступа следуют несколько иному правилу. Представление обозначенного подтипа (представление) типа доступа в данном месте определяется представлением обозначенного подтипа, которое видно в этом месте, а не представлением в месте объявления типа доступа.
Тип является потомком полного представления некоторого предка его родительского типа только в том случае, если текущее представление, которым он обладает, его родителя является потомком полного представления этого предка. Более общим образом, в любом данном месте тип происходит от того же представления предка, что и текущее представление его родителя. Это представление определяет, какие характеристики наследуются от предка и, например, считается ли тип потомком типа записи или потомком только через расширения записи более далекого предка.
Кроме того, возможно, что существуют места, где известно, что производный тип косвенно происходит от типа-предка, но он не является потомком даже частичного представления типа-предка, потому что родитель этого производного типа не является видимым потомком предка. В этом случае производный тип не наследует никаких характеристик от этого предка, но тем не менее находится в классе производных предка для целей преобразования типов, отношения "покрывает" и соответствия формальному производному типу. В этом случае производный тип фактически является потомком неполного представления предка.
Наследуемые примитивные подпрограммы следуют другому правилу. Для derived_type_definition каждая наследуемая примитивная подпрограмма неявно объявляется в самом раннем месте, если таковое имеется, непосредственно внутри области объявления, в которой встречается type_declaration, но после type_declaration, где соответствующее объявление из родителя является видимым. Если такого места нет, то наследуемая подпрограмма не объявляется вообще, но она все равно существует. Для помеченного типа возможно обращение к наследуемой подпрограмме, которая вообще не объявлена.
Для private_extension_declaration каждая наследуемая подпрограмма объявляется непосредственно после private_extension_declaration, если соответствующее объявление из предка является видимым в этом месте. В противном случае наследуемая подпрограмма не объявляется для частного расширения, хотя она может быть для полного типа.
Атрибут Class определен для помеченных подтипов в 3.9. Кроме того, для каждого подтипа S неопознанного закрытого типа, полное представление которого помечено, определен следующий атрибут:
S'Class
Обозначает подтип класса, соответствующий полному представлению S. Этот атрибут разрешен только с начала закрытой части, в которой объявлено полное представление, до объявления полного представления. После полного представления атрибут Class полного представления может быть использован.
ПРИМЕЧАНИЕ 1 Поскольку частичное представление и полное представление являются двумя разными представлениями одного и того же типа, за пределами определяющего пакета характеристики типа определяются видимой частью. Внутри этих внешних программных модулей тип просто является закрытым типом или закрытым расширением, и любое языковое правило, которое применяется только к другому классу типов, не применяется. Тот факт, что полное объявление может реализовать закрытый тип с типом определенного класса (например, как тип массива), имеет значение только внутри области объявления самого пакета, включая все дочерние модули.
Однако следствия этой фактической реализации действительны везде. Например: любое значение по умолчанию для компонентов выполняется; атрибут Size предоставляет размер полного представления; завершение все еще выполняется для управляемых компонентов полного представления; правила зависимости задач все еще применяются к компонентам, которые являются объектами задач.
ПРИМЕЧАНИЕ 2 Частичные представления обеспечивают инициализацию, проверки на принадлежность, выбранные компоненты для выбора дискриминантов и наследуемых компонентов, квалификацию и явное преобразование. Неограниченные частичные представления также позволяют использовать assignment_statements.
ПРИМЕЧАНИЕ 3 Для подтипа S частичного представления определен S'Size (см. 13.3). Для объекта A частичного представления определены атрибуты A'Size и A'Address (см. 13.3). Атрибуты Position, First_Bit и Last_Bit также определены для дискриминантов и наследуемых компонентов.

Примеры

Пример типа с закрытыми операциями:
package Key_Manager is
type Key is private;
Null_Key : constant Key; -- отложенное объявление константы (см. 7.4)
procedure Get_Key(K : out Key);
function "<" (X, Y : Key) return Boolean;
private
type Key is new Natural;
Null_Key : constant Key := Key'First;
end Key_Manager;
package body Key_Manager is
Last_Key : Key := Null_Key;
procedure Get_Key(K : out Key) is
begin
Last_Key := Last_Key + 1;
K := Last_Key;
end Get_Key;
function "<" (X, Y : Key) return Boolean is
begin
return Natural(X) < Natural(Y);
end "<";
end Key_Manager;
За пределами пакета Key_Manager доступные операции для объектов типа Key включают присваивание, сравнение на равенство или неравенство, процедуру Get_Key и оператор "<"; они не включают другие реляционные операторы, такие как ">=", или арифметические операторы.
Явно объявленный оператор "<" скрывает предопределенный оператор "<", неявно объявленный full_type_declaration. В теле функции необходимо явное преобразование X и Y в подтип Natural для вызова оператора "<" родительского типа. В качестве альтернативы, результат функции можно записать как not (X >= Y), так как оператор ">=" не переопределен.
Значение переменной Last_Key, объявленной в теле пакета, остается неизменным между вызовами процедуры Get_Key. (См. также ПРИМЕЧАНИЯ 7.2.)


Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API