Contents Index Previous Next
3.9.1 Type Extensions
1
[
{type extension}
{extension (of a type)}
{record extension} {extension
(of a record type)} {private
extension} {extension
(of a private type)} Every type extension
is a tagged type, and is either a
record extension or a
private
extension of some other tagged type.]
Language Design Principles
1.a
We want to make sure that we can
extend a generic formal tagged type, without knowing its discriminants.
1.b
We don't want to allow components
in an extension aggregate to depend on discriminants inherited from the
parent value, since such dependence requires staticness in aggregates,
at least for variants.
Syntax
2
record_extension_part
::= with record_definition
Legality Rules
3
The parent type of a record extension shall
not be a class-wide type. If the parent type is nonlimited, then each of the
components of the
record_extension_part
shall be nonlimited.
{accessibility rule (record extension)
[partial]} The accessibility level (see
3.10.2)
of a record extension shall not be statically deeper than that of its parent
type.
{generic contract issue [partial]} In
addition to the places where Legality Rules normally apply (see
12.3),
these rules apply also in the private part of an instance of a generic unit.
3.a
Reason: If the parent is
a limited formal type, then the actual might be nonlimited.
3.b
A similar accessibility rule is
not needed for private extensions, because in a package, the rule will
apply to the full_type_declaration,
and for a generic formal private extension, the actual is all that matters.
4
A type extension shall not be declared in a generic
body if the parent type is declared outside that body.
4.a
Reason: This paragraph
ensures that a dispatching call will never attempt to execute an inaccessible
subprogram body.
4.b
The part about generic bodies
is necessary in order to preserve the contract model.
4.c
Since
a generic unit can be instantiated at a deeper accessibility level than
the generic unit, it is necessary to prevent type extensions whose parent
is declared outside the generic unit. The same is true if the parent
is a formal of the generic unit. If the parent is declared in the generic_declaration
(but is not a formal), we don't run afoul of the accessibility rules,
because we know that the instance declaration and body will be at the
same accessibility level. However, we still have a problem in that case,
because it might have an unknown number of abstract subprograms, as in
the following example:
4.d
package P is
type T is tagged null record;
function F return T; -- Inherited versions will be abstract.
end P;
4.e
generic
type TT is tagged private;
package Gp is
type NT is abstract new TT with null record;
procedure Q(X : in NT) is abstract;
end Gp;
4.f
package body Gp is
type NT2 is new NT with null record; -- Illegal!
procedure Q(X : in NT2) is begin null; end Q;
-- Is this legal or not? Can't decide because
-- we don't know whether TT had any functions that go abstract
-- on extension.
end Gp;
4.g
package I is new Gp(TT => P.T);
4.h
I.NT is an abstract type with
two abstract subprograms: F (inherited as abstract) and Q (explicitly
declared as abstract). But the generic body doesn't know about F, so
we don't know that it needs to be overridden to make a nonabstract extension
of NT. Furthermore, a formal tagged limited private type can be extended
with limited components, but the actual might not be limited, which would
allow assignment of limited types, which is bad. Hence, we have to disallow
this case as well.
4.i
If TT were declared as abstract,
then we could have the same problem with abstract procedures.
4.j
We considered disallowing all
tagged types in a generic body, for simplicity. We decided not to go
that far, in order to avoid unnecessary restrictions.
4.k
{accessibility rule (not part
of generic contract) [partial]} We also considered
trying make the accessibility level part of the contract; i.e. invent
some way of saying (in the generic_declaration)
``all instances of this generic unit will have the same accessibility
level as the generic_declaration.''
Unfortunately, that doesn't solve the part of the problem having to do
with abstract types.
4.l
Children of generic units obviate
the need for extension in the body somewhat.
Dynamic Semantics
5
{elaboration (record_extension_part)
[partial]} The elaboration of a
record_extension_part
consists of the elaboration of the
record_definition.
6
66 The term ``type extension''
refers to a type as a whole. The term ``extension part'' refers to the
piece of text that defines the additional components (if any) the type
extension has relative to its specified ancestor type.
6.a
Discussion: We considered
other terminology, such as ``extended type.'' However, the terms ``private
extended type'' and ``record extended type'' did not convey the proper
meaning. Hence, we have chosen to uniformly use the term ``extension''
as the type resulting from extending a type, with ``private extension''
being one produced by privately extending the type, and ``record extension''
being one produced by extending the type with an additional record-like
set of components. Note also that the term ``type extension'' refers
to the result of extending a type in the language Oberon as well (though
there the term ``extended type'' is also used, interchangeably, perhaps
because Oberon doesn't have the concept of a ``private extension'').
7
67 The accessibility rules
imply that a tagged type declared in a library package_specification
can be extended only at library level or as a generic formal. When the
extension is declared immediately within a package_body,
primitive subprograms are inherited and are overridable, but new primitive
subprograms cannot be added.
8
68 A name
that denotes a component (including a discriminant) of the parent type is not
allowed within the record_extension_part.
Similarly, a name that denotes a component
defined within the record_extension_part
is not allowed within the record_extension_part.
It is permissible to use a name that denotes
a discriminant of the record extension, providing there is a new known_discriminant_part
in the enclosing type declaration. (The full rule is given in 3.8.)
8.a
Reason: The restriction
against depending on discriminants of the parent is to simplify the definition
of extension aggregates. The restriction against using parent components
in other ways is methodological; it presumably simplifies implementation
as well.
9
69 Each visible component of a record
extension has to have a unique name, whether the component is (visibly) inherited
from the parent type or declared in the record_extension_part
(see 8.3).
Examples
10
Examples
of record extensions (of types defined above in 3.9):
11
type Painted_Point is new Point with
record
Paint : Color := White;
end record;
-- Components X and Y are inherited
12
Origin : constant Painted_Point := (X | Y => 0.0, Paint => Black);
13
type Literal is new Expression with
record -- a leaf in an Expression tree
Value : Real;
end record;
14
type Expr_Ptr is access all Expression'Class;
-- see 3.10
15
type Binary_Operation is new Expression with
record -- an internal node in an Expression tree
Left, Right : Expr_Ptr;
end record;
16
type Addition is new Binary_Operation with null record;
type Subtraction is new Binary_Operation with null record;
-- No additional components needed for these extensions
17
Tree : Expr_Ptr := -- A tree representation of ``5.0 + (13.0-7.0)''
new Addition'(
Left => new Literal'(Value => 5.0),
Right => new Subtraction'(
Left => new Literal'(Value => 13.0),
Right => new Literal'(Value => 7.0)));
Extensions to Ada 83
17.a
{extensions to Ada 83}
Type extension is a new concept.
Contents Index Previous Next Legal