3.9 Tagged Types and Type Extensions
Tagged types and type extensions support object-oriented programming, based on inheritance with extension and run-time polymorphism via dispatching operations.
A record type or private type that has the reserved word tagged in its declaration is called a tagged type. When deriving from a tagged type, additional components may be defined. 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 the ancestor type, or simply a type extension. Every type extension is also a tagged type, and is either a record extension or a private extension of some other tagged type. A record extension is defined by a derived_type_definition with a record_extension_part. A private extension, which is a partial view of a record extension, can be declared in the visible part of a package (see 7.3) or in a generic formal part (see 12.5.1).
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.
The tag of a specific tagged type identifies the full_type_declaration of the type. 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, the language does not specify whether repeated instantiations of the generic body result in distinct tags.
The following language-defined library package exists:
package Ada.Tags is
type Tag is private;
function Expanded_Name(T : Tag) return String;
function External_Tag(T : Tag) return String;
function Internal_Tag(External : String) return Tag;
Tag_Error : exception;
... -- not specified by the language
The function 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.
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).
The function Internal_Tag returns the 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.
For every subtype S of a tagged type T (specific or class-wide), the following attributes are defined:
- 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).
- 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.
- 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.
Given a prefix X that is of a class-wide tagged type (after any implicit dereference), the following attribute is defined:
- X'Tag denotes the tag of X. The value of this attribute is of type Tag.
The tag associated with an object of a tagged type is determined as follows:
- The tag of a stand-alone object, a component, or an aggregate of a specific tagged type T identifies T.
- The tag of an object created by an allocator for an access type with a specific designated tagged type T, identifies T.
- The tag of an object of a class-wide tagged type is that of its initialization expression.
- The tag of the result returned by a function whose result type is a specific tagged type T identifies T.
- The tag of the result returned by a function with a class-wide result type is that of the return expression.
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).
The implementation of the functions in Ada.Tags may raise Tag_Error if no specific type corresponding to the tag passed as a parameter exists in the partition at the time the function is called.
62 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.
63 Once an object has been created, its tag never changes.
64 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.
65 If S denotes an untagged private type whose full type is tagged, then S'Class is also allowed before the full type definition, but only in the private part of the package in which the type is declared (see 7.3.1). Similarly, the Class attribute is defined for incomplete types whose full type is tagged, but only within the library unit in which the incomplete type is declared (see 3.10.1).
Examples of tagged record types:
type Point is tagged
X, Y : Real := 0.0;
type Expression is tagged null record;
-- Components will be added by each extension
Copyright © 1992,1993,1994,1995 Intermetrics, Inc.
Copyright © 2000 The MITRE Corporation, Inc. Ada Reference Manual