Contents Index Search Previous Next
7.3.1 Private Operations
For a type declared in the visible part of a package
or generic package, certain operations on the type do not become visible
until later in the package -- either in the private part or the body.
Such private operations
are available only
inside the declarative region of the package or generic package.
The predefined operators that exist for a given
type are determined by the classes to which the type belongs. For example,
an integer type has a predefined "+" operator. In most cases,
the predefined operators of a type are declared immediately after the
definition of the type; the exceptions are explained below. Inherited
subprograms are also implicitly declared immediately after the definition
of the type, except as stated below.
For a composite type, the characteristics (see
) of the type are determined in part by
the characteristics of its component types. At the place where the composite
type is declared, the only characteristics of component types used are
those characteristics visible at that place. If later immediately within
the declarative region in which the composite type is declared additional
characteristics become visible for a component type, then any corresponding
characteristics become visible for the composite type. Any additional
predefined operators are implicitly declared at that place.
The corresponding rule applies to a type defined
by a derived_type_definition, if
there is a place immediately within the declarative region in which the
type is declared where additional characteristics of its parent type
example, an array type whose component type is limited private becomes
nonlimited if the full view of the component type is nonlimited and visible
at some later place immediately within the declarative region in which
the array type is declared. In such a case, the predefined "="
operator is implicitly declared at that place, and assignment is allowed
after that place.
Inherited primitive subprograms follow a different
rule. For a derived_type_definition,
each inherited primitive subprogram is implicitly declared at the earliest
place, if any, immediately within the declarative region in which the
type_declaration occurs, but after
the type_declaration, where the
corresponding declaration from the parent is visible. If there is no
such place, then the inherited subprogram is not declared at all. An
inherited subprogram that is not declared at all cannot be named in a
call and cannot be overridden, but for a tagged type, it is possible
to dispatch to it.
For a private_extension_declaration,
each inherited subprogram is declared immediately after the private_extension_declaration
if the corresponding declaration from the ancestor is visible at that
place. Otherwise, the inherited subprogram is not declared for the private
extension, though it might be for the full type.
The Class attribute
is defined for tagged subtypes in 3.9
. In addition,
for every subtype S of an untagged private type whose full view is tagged,
the following attribute is defined:
Denotes the class-wide subtype
corresponding to the full view of S. This attribute is allowed only from
the beginning of the private part in which the full view is declared,
until the declaration of the full view. After the full view, the Class
attribute of the full view can be used.
8 Because a partial view
and a full view are two different views of one and the same type, outside
of the defining package the characteristics of the type are those defined
by the visible part. Within these outside program units the type is just
a private type or private extension, and any language rule that applies
only to another class of types does not apply. The fact that the full
declaration might implement a private type with a type of a particular
class (for example, as an array type) is relevant only within the declarative
region of the package itself including any child units.
The consequences of this actual implementation
are, however, valid everywhere. For example: any default initialization
of components takes place; the attribute Size provides the size of the
full view; finalization is still done for controlled components of the
full view; task dependence rules still apply to components that are task
9 Partial views provide
assignment (unless the view is limited), membership tests, selected components
for the selection of discriminants and inherited components, qualification,
and explicit conversion.
10 For a subtype S of a
partial view, S'Size is defined (see 13.3).
For an object A of a partial view, the attributes A'Size and A'Address
are defined (see 13.3). The Position, First_Bit,
and Last_Bit attributes are also defined for discriminants and inherited
Example of a
type with private operations:
package Key_Manager is
type Key is private;
Null_Key : constant Key; -- a deferred constant declaration (see 7.4)
procedure Get_Key(K : out Key);
function "<" (X, Y : Key) return Boolean;
type Key is new Natural;
Null_Key : constant Key := Key'First;
package body Key_Manager is
Last_Key : Key := Null_Key;
procedure Get_Key(K : out Key) is
Last_Key := Last_Key + 1;
K := Last_Key;
function "<" (X, Y : Key) return Boolean is
return Natural(X) < Natural(Y);
11 Notes on the example:
Outside of the package Key_Manager, the operations available for objects
of type Key include assignment, the comparison for equality or inequality,
the procedure Get_Key and the operator "<"; they do not
include other relational operators such as ">=", or arithmetic
The explicitly declared operator "<"
hides the predefined operator "<" implicitly declared by
the full_type_declaration. Within
the body of the function, an explicit conversion of X and Y to the subtype
Natural is necessary to invoke the "<" operator of the parent
type. Alternatively, the result of the function could be written as not
(X >= Y), since the operator ">=" is not redefined.
The value of the variable Last_Key,
declared in the package body, remains unchanged between calls of the
procedure Get_Key. (See also the NOTES of 7.2.)
Contents Index Search Previous Next Legal