3.9.3 Abstract Types and Subprograms
An 
abstract type is a tagged type intended for use as an ancestor 
of other types, but which is not allowed to have objects of its own. 
An 
abstract subprogram 
is a subprogram that has no body, but is intended to be overridden at 
some point when inherited. Because objects of an abstract type cannot 
be created, a dispatching call to an abstract subprogram always dispatches 
to some overriding body. 
 
Syntax
Static Semantics
  Interface 
types (see 
3.9.4) are abstract types. In 
addition, a tagged type that has the reserved word 
abstract in 
its declaration is an abstract type. The class-wide type (see 
3.4.1) 
rooted at an abstract type is not itself an abstract type. 
 
Legality Rules
Only a tagged type shall have the reserved word abstract 
in its declaration. 
If a type has an implicitly 
declared primitive subprogram that is inherited or is a predefined operator, 
and the corresponding primitive subprogram of the parent or ancestor 
type is abstract or is a function with a controlling access result, or 
if a type other than a nonabstract null extension inherits a function 
with a controlling result, then: 
If the type is abstract or untagged, the implicitly 
declared subprogram is abstract. 
Otherwise, the subprogram shall be overridden with 
a nonabstract subprogram or, in the case of a private extension inheriting 
a nonabstract function with a controlling result, have a full type that 
is a null extension; for a type declared in the visible part of a package, 
the overriding may be either in the visible or the private part. Such 
a subprogram is said to 
require overriding.
 
However, if the type is a generic formal type, the subprogram need not 
be overridden for the formal type itself; a nonabstract version will 
necessarily be provided by the actual type. 
 
A call on an abstract subprogram shall be a dispatching 
call; nondispatching calls to an abstract subprogram are not allowed. 
The type of an 
aggregate, 
or of an object created by an 
object_declaration 
or an 
allocator, 
or a generic formal object of mode 
in, shall not be abstract. 
The type of the target of an assignment operation (see 
5.2) 
shall not be abstract. The type of a component shall not be abstract. 
If the result type of a function is abstract, then the function shall 
be abstract. If a function has an access result type designating an abstract 
type, then the function shall be abstract. The type denoted by a 
return_subtype_indication 
(see 
6.5) shall not be abstract. A generic 
function shall not have an abstract result type or an access result type 
designating an abstract type. 
 
If a partial view is not abstract, the corresponding 
full view shall not be abstract. If a generic formal type is abstract, 
then for each primitive subprogram of the formal that is not abstract, 
the corresponding primitive subprogram of the actual shall not be abstract. 
 For an abstract type declared in a visible part, 
an abstract primitive subprogram shall not be declared in the private 
part, unless it is overriding an abstract subprogram implicitly declared 
in the visible part. For a tagged type declared in a visible part, a 
primitive function with a controlling result or a controlling access 
result shall not be declared in the private part, unless it is overriding 
a function implicitly declared in the visible part. 
Dynamic Semantics
82  Abstractness is not inherited; to declare 
an abstract type, the reserved word abstract has to be used in 
the declaration of the type extension. 
83  A class-wide type is never abstract. 
Even if a class is rooted at an abstract type, the class-wide type for 
the class is not abstract, and an object of the class-wide type can be 
created; the tag of such an object will identify some nonabstract type 
in the class. 
Examples
Example of an abstract 
type representing a set of natural numbers: 
package Sets is
    subtype Element_Type is Natural;
    type Set is abstract tagged null record;
    function Empty return Set is abstract;
    function Union(Left, Right : Set) return Set is abstract;
    function Intersection(Left, Right : Set) return Set is abstract;
    function Unit_Set(Element : Element_Type) return Set is abstract;
    procedure Take(Element : out Element_Type;
                   From : in out Set) is abstract;
end Sets;
84  Notes on the example: Given the 
above abstract type, one could then derive various (nonabstract) extensions 
of the type, representing alternative implementations of a set. One might 
use a bit vector, but impose an upper bound on the largest element representable, 
while another might use a hash table, trading off space for flexibility. 
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe