Go to the first, previous, next, last section, table of contents.
-
The declaration (in the visible part of a package) of a type as a
private type or private extension serves to separate the characteristics
that can be used directly by outside program units (that is, the logical
properties) from other characteristics whose direct use is confined to
the package (the details of the definition of the type itself).
See section 3.9.1 Type Extensions, for an overview of type extensions.
Syntax
-
private_type_declaration ::=
type defining_identifier [discriminant_part] is
[[abstract] tagged] [limited] private;
-
private_extension_declaration ::=
type defining_identifier [discriminant_part] is
[abstract] new ancestor_subtype_indication with private;
Legality Rules
-
A private_type_declaration or private_extension_declaration declares a
partial view of the type; such a declaration is allowed only as a
declarative_item of the visible part of a package, and it requires a
completion, which shall be a full_type_declaration that occurs as a
declarative_item of the private part of the package. The view of the
type declared by the full_type_declaration is called the full view. A
generic formal private type or a generic formal private extension is
also a partial view.
-
A type shall be completely defined before it is frozen, See section 3.11.1 Completions of Declarations,
and See section 13.14 Freezing Rules. Thus, neither the declaration of a variable of a
partial view of a type, nor the creation by an allocator of an object of
the partial view are allowed before the full declaration of the type.
Similarly, before the full declaration, the name of the partial view
cannot be used in a generic_instantiation or in a representation item.
-
A private type is limited if its declaration includes the reserved word
limited; a private extension is limited if its ancestor type is limited.
If the partial view is nonlimited, then the full view shall be
nonlimited. If a tagged partial view is limited, then the full view
shall be limited. On the other hand, if an untagged partial view is
limited, the full view may be limited or nonlimited.
-
If the partial view is tagged, then the full view shall be tagged. On
the other hand, if the partial view is untagged, then the full view may
be tagged or untagged. In the case where the partial view is untagged
and the full view is tagged, no derivatives of the partial view are
allowed within the immediate scope of the partial view; derivatives of
the full view are allowed.
-
The ancestor subtype of a private_extension_declaration is the subtype
defined by the ancestor_subtype_indication; the ancestor type shall be a
specific tagged type. The full view of a private extension shall be
derived (directly or indirectly) from the ancestor type. In addition to
the places where Legality Rules normally apply, See section 12.3 Generic Instantiation, the
requirement that the ancestor be specific applies also in the private
part of an instance of a generic unit.
-
If the declaration of a partial view includes a known_discriminant_part,
then the full_type_declaration shall have a fully conforming (explicit)
known_discriminant_part, See section 6.3.1 Conformance Rules. The
ancestor subtype may be unconstrained; the parent subtype of the full
view is required to be constrained, See section 3.7 Discriminants.
-
If a private extension inherits known discriminants from the ancestor
subtype, then the full view shall also inherit its discriminants from
the ancestor subtype, and the parent subtype of the full view shall be
constrained if and only if the ancestor subtype is constrained.
-
If a partial view has unknown discriminants, then the
full_type_declaration may define a definite or an indefinite subtype,
with or without discriminants.
-
If a partial view has neither known nor unknown discriminants, then the
full_type_declaration shall define a definite subtype.
-
If the ancestor subtype of a private extension has constrained
discriminants, then the parent subtype of the full view shall impose a
statically matching constraint on those discriminants.
Static Semantics
-
A private_type_declaration declares a private type and its first
subtype. Similarly, a private_extension_declaration declares a private
extension and its first subtype.
-
A declaration of a partial view and the corresponding
full_type_declaration define two views of a single type. The declaration
of a partial view together with the visible part define the operations
that are available to outside program units; the declaration of the full
view together with the private part define other operations whose direct
use is possible only within the declarative region of the package
itself. Moreover, within the scope of the declaration of the full view,
the characteristics of the type are determined by the full view; in
particular, within its scope, the full view determines the classes that
include the type, which components, entries, and protected subprograms
are visible, what attributes and other predefined operations are
allowed, and whether the first subtype is static. See section 7.3.1 Private Operations.
-
A private extension inherits components (including discriminants unless
there is a new discriminant_part specified) and user-defined primitive
subprograms from its ancestor type, in the same way that a record
extension inherits components and user-defined primitive subprograms
from its parent type, See section 3.4 Derived Types and Classes.
Dynamic Semantics
-
The elaboration of a private_type_declaration creates a partial view of
a type. The elaboration of a private_extension_declaration elaborates
the ancestor_subtype_indication, and creates a partial view of a type.
NOTES
-
(5) The partial view of a type as declared by a private_type_declaration
is defined to be a composite view (in 3.2). The full view of the type
might or might not be composite. A private extension is also composite,
as is its full view.
-
(6) Declaring a private type with an unknown_discriminant_part is a way
of preventing clients from creating uninitialized objects of the type;
they are then forced to initialize each object by calling some operation
declared in the visible part of the package. If such a type is also
limited, then no objects of the type can be declared outside the scope
of the full_type_declaration, restricting all object creation to the
package defining the type. This allows complete control over all storage
allocation for the type. Objects of such a type can still be passed as
parameters, however.
-
(7) The ancestor type specified in a private_extension_declaration and
the parent type specified in the corresponding declaration of a record
extension given in the private part need not be the same -- the parent
type of the full view can be any descendant of the ancestor type. In
this case, for a primitive subprogram that is inherited from the
ancestor type and not overridden, the formal parameter names and default
expressions (if any) come from the corresponding primitive subprogram of
the specified ancestor type, while the body comes from the corresponding
primitive subprogram of the parent type of the full view. See section 3.9.2 Dispatching Operations of Tagged Types.
Examples
-
Examples of private type declarations:
-
type Key is private;
type File_Name is limited private;
-
Example of a private extension declaration:
-
type List is new Ada.Finalization.Controlled with private;
- 7.3.1: Private Operations
Go to the first, previous, next, last section, table of contents.