Contents Index Search Related Documents Previous Next
3.9 Tagged Types and Type Extensions
1
Tagged
types and type extensions support object-oriented programming, based
on inheritance with extension and run-time polymorphism via
dispatching
operations.
Static Semantics
2/2
A record type or private
type that has the reserved word
tagged in its declaration is called
a
tagged type. In addition, an interface type is a tagged type
(see
3.9.4). When deriving from a tagged
type, as for any derived type, additional primitive subprograms may be
defined, and inherited primitive subprograms may be overridden.
The
derived type is called an
extension of its ancestor type(s), or
simply a
type extension.
2.1/2
Every
type extension is also a tagged type, and is either a
record extension
of some other tagged type, a
private extension, or a task or protected
type derived from an interface type (a synchronized tagged type —
see
3.9.4). A record extension is defined
by a
derived_type_definition with
a
record_extension_part (see
3.9.1),
which may include the definition of additional components. A private
extension, which is a partial view of a record extension or of a synchronized
tagged type, can be declared in the visible part of a package (see
7.3)
or in a generic formal part (see
12.5.1).
3
An object of a tagged type
has an associated (run-time)
tag that identifies the specific
tagged type used to create the object originally. The tag of an operand
of a class-wide tagged type
T'Class controls which subprogram
body is to be executed when a primitive subprogram of type
T is
applied to the operand (see
3.9.2);
using
a tag to control which body to execute is called
dispatching.
4/2
The tag of a specific tagged type identifies
the full_type_declaration of the
type, and for a type extension, is sufficient to uniquely identify the
type among all descendants of the same ancestor. If a declaration for
a tagged type occurs within a generic_package_declaration,
then the corresponding type declarations in distinct instances of the
generic package are associated with distinct tags. For a tagged type
that is local to a generic package body and with all of its ancestors
(if any) also local to the generic body, the language does not specify
whether repeated instantiations of the generic body result in distinct
tags.
5
The following language-defined
library package exists:
6/2
package Ada.Tags is
pragma Preelaborate(Tags);
type Tag is private;
6.1/2
7/2
function Expanded_Name(T : Tag) return String;
function Wide_Expanded_Name(T : Tag) return Wide_String;
function Wide_Wide_Expanded_Name(T : Tag) return Wide_Wide_String;
function External_Tag(T : Tag) return String;
function Internal_Tag(External : String) return Tag;
7.1/2
function Descendant_Tag(External : String; Ancestor : Tag) return Tag;
function Is_Descendant_At_Same_Level(Descendant, Ancestor : Tag)
return Boolean;
7.2/2
function Parent_Tag (T : Tag) return Tag;
7.3/2
type Tag_Array is array (Positive range <>) of Tag;
7.4/2
function Interface_Ancestor_Tags (T : Tag) return Tag_Array;
8
9
private
... -- not specified by the language
end Ada.Tags;
9.1/2
No_Tag is the default initial value of type
Tag.
10/2
The function Wide_Wide_Expanded_Name returns
the full expanded name of the first subtype of the specific type identified
by the tag, in upper case, starting with a root library unit. The result
is implementation defined if the type is declared within an unnamed block_statement.
10.1/2
The function Expanded_Name (respectively,
Wide_Expanded_Name) returns the same sequence of graphic characters as
that defined for Wide_Wide_Expanded_Name, if all the graphic characters
are defined in Character (respectively, Wide_Character); otherwise, the
sequence of characters is implementation defined, but no shorter than
that returned by Wide_Wide_Expanded_Name for the same value of the argument.
11
The function External_Tag returns a string to
be used in an external representation for the given tag. The call External_Tag(S'Tag)
is equivalent to the
attribute_reference
S'External_Tag (see
13.3).
11.1/2
The string returned by the functions Expanded_Name,
Wide_Expanded_Name, Wide_Wide_Expanded_Name, and External_Tag has lower
bound 1.
12/2
The function Internal_Tag returns a tag that
corresponds to the given external tag, or raises Tag_Error if the given
string is not the external tag for any specific type of the partition.
Tag_Error is also raised if the specific type identified is a library-level
type whose tag has not yet been created (see
13.14).
12.1/2
The function Descendant_Tag returns the (internal)
tag for the type that corresponds to the given external tag and is both
a descendant of the type identified by the Ancestor tag and has the same
accessibility level as the identified ancestor. Tag_Error is raised if
External is not the external tag for such a type. Tag_Error is also raised
if the specific type identified is a library-level type whose tag has
not yet been created.
12.2/2
The function Is_Descendant_At_Same_Level
returns True if Descendant tag identifies a type that is both a descendant
of the type identified by Ancestor and at the same accessibility level.
If not, it returns False.
12.3/2
The function Parent_Tag returns the tag of
the parent type of the type whose tag is T. If the type does not have
a parent type (that is, it was not declared by a derived_type_declaration),
then No_Tag is returned.
12.4/2
The function Interface_Ancestor_Tags returns
an array containing the tag of each interface ancestor type of the type
whose tag is T, other than T itself. The lower bound of the returned
array is 1, and the order of the returned tags is unspecified. Each tag
appears in the result exactly once. If the type whose tag is T has no
interface ancestors, a null array is returned.
13
For every subtype S of a tagged type T
(specific or class-wide), the following attributes are defined:
14
- S'Class
-
S'Class denotes a subtype of
the class-wide type (called T'Class in this International Standard)
for the class rooted at T (or if S already denotes a class-wide
subtype, then S'Class is the same as S).
15
- S'Class
is unconstrained. However, if S is constrained, then the values of S'Class
are only those that when converted to the type T belong to S.
16
- S'Tag
-
S'Tag denotes the tag of the
type T (or if T is class-wide, the tag of the root type
of the corresponding class). The value of this attribute is of type Tag.
17
Given a prefix
X that is of a class-wide tagged type (after any implicit dereference),
the following attribute is defined:
18
- X'Tag
-
X'Tag denotes the tag of X. The
value of this attribute is of type Tag.
18.1/2
The following
language-defined generic function exists:
18.2/2
generic
type T (<>) is abstract tagged limited private;
type Parameters (<>) is limited private;
with function Constructor (Params : access Parameters)
return T is abstract;
function Ada.Tags.Generic_Dispatching_Constructor
(The_Tag : Tag;
Params : access Parameters) return T'Class;
pragma Preelaborate (Generic_Dispatching_Constructor);
pragma Convention (Intrinsic, Generic_Dispatching_Constructor);
18.3/2
Tags.Generic_Dispatching_Constructor provides
a mechanism to create an object of an appropriate type from just a tag
value. The function Constructor is expected to create the object given
a reference to an object of type Parameters.
Dynamic Semantics
19
The tag associated
with an object of a tagged type is determined as follows:
20
- The tag of a stand-alone
object, a component, or an aggregate
of a specific tagged type T identifies T.
21
- The tag of an
object created by an allocator for an access type with a specific designated
tagged type T, identifies T.
22
- The tag of an
object of a class-wide tagged type is that of its initialization expression.
23
- The tag of the
result returned by a function whose result type is a specific tagged
type T identifies T.
24/2
- The tag of the
result returned by a function with a class-wide result type is that of
the return object.
25
The tag is preserved by type
conversion and by parameter passing. The tag of a value is the tag of
the associated object (see
6.2).
25.1/2
Tag_Error is raised by a call of Descendant_Tag,
Expanded_Name, External_Tag, Interface_Ancestor_Tag, Is_Descendant_At_Same_Level,
or Parent_Tag if any tag passed is No_Tag.
25.2/2
An instance of Tags.Generic_Dispatching_Constructor
raises Tag_Error if The_Tag does not represent a concrete descendant
of T. Otherwise, it dispatches to the primitive function denoted by the
formal Constructor for the type identified by the tag The_Tag, passing
Params, and returns the result. Any exception raised by the function
is propagated.
Erroneous Execution
25.3/2
If the internal tag provided
to an instance of Tags.Generic_Dispatching_Constructor identifies a type
that is not library-level and whose tag has not been created (see
13.14),
or does not exist in the partition at the time of the call, execution
is erroneous.
Implementation Permissions
26/2
The implementation of the functions in Ada.Tags
may raise Tag_Error if no specific type corresponding to the tag or external
tag passed as a parameter exists in the partition at the time the function
is called.
27
64 A type declared with
the reserved word tagged should normally be declared in a package_specification,
so that new primitive subprograms can be declared for it.
28
65 Once an object has been
created, its tag never changes.
29
66 Class-wide types are
defined to have unknown discriminants (see 3.7).
This means that objects of a class-wide type have to be explicitly initialized
(whether created by an object_declaration
or an allocator), and that aggregates
have to be explicitly qualified with a specific type when their expected
type is class-wide.
30/2
This paragraph
was deleted.67
30.1/2
68 The capability provided
by Tags.Generic_Dispatching_Constructor is sometimes known as a factory.
Examples
31
Examples of
tagged record types:
32
type Point is tagged
record
X, Y : Real := 0.0;
end record;
33
type Expression is tagged null record;
-- Components will be added by each extension
Contents Index Search Related Documents Previous Next Legal