Design Article
High-integrity object-oriented programming with Ada – Part 2
Benjamin M. Brosgol, AdaCore
7/27/2011 8:26 AM EDT
Inheritance
Inheritance in Ada is captured by type derivation, where a new tagged type (the derived type, corresponding to a subclass) is declared as an extension of an existing tagged type (the parent type, corresponding to the superclass). Type extension is as described in Part 1 of the series:
• All fields in the parent tagged type are present in the derived type
• New fields can be added in the extension part
• Primitive operations of the parent type are implicitly inherited unless overridden
• New primitive operations may be declared for the derived type
Ada supports single implementation inheritance and multiple interface inheritance. Thus a tagged type can inherit from at most one non-interface type and an arbitrary number of interface types. The types (parent tagged type, interface types) that the new tagged type is deriving from are referred to as the progenitors of the new type.
Here is an example of inheritance in Ada:
with Encryptable_Pkg;
with Ada.Strings.Unbounded;
package Node_Pkg.DataNode_Pkg is
type DataNode is new Node_Pkg.Node and Encryptable_Pkg.Encryptable with
-- extension part
record
Data : Ada.Strings.Unbounded.Unbounded_String;
end record;
overriding procedure Write (Item : in DataNode);
overriding procedure Read (Item : out DataNode);
overriding procedure Encrypt (Item : in out DataNode);
overriding procedure Decrypt (Item : in out DataNode);
end Node_Pkg.DataNode_Pkg;
The tagged type DataNode inherits from both the parent type Node and the interface Encryptable. Declaring DataNode_Pkg as a child of Node_Pkg—evidenced by the name Node_Packaging.DataNode_Pkg—allows the implementation of DataNode’s operations to access the representation of type Node in the private part of Node_Pkg. A DataNode object contains an Id field, from the parent type Node, and a Data field. The Get_Id and Set_Id procedures from Node are implicitly derived for DataNode with the signatures:
procedure Set_Id (Item : in DataNode; Id : in Integer);
function Id (Item : in DataNode) return Integer;
All the other procedures explicitly override the corresponding versions of the procedures for the tagged type Node and the interface Encryptable; the use of the reserved word overriding makes this intent clear. It is a compile-time error if a subprogram marked as overriding does not override a primitive operation of a progenitor type.
A subprogram parameter having a tagged type is always passed by reference. An inherited subprogram such as Set_Id or Id operates on an object of the derived type, but only has the parent type’s view of the object and thus can only access fields defined by the parent type.
An inheritance hierarchy rooted at a tagged type T, which may be an interface type, is denoted by the so-called class-wide type T’Class. An object of type T’Class is either an object of type T or else an object of some specific tagged type U that derives directly or indirectly from T. Polymorphism in Ada is generally modeled by a variable of an access type, or pointer, whose designated type is class-wide.
The following declarations define types for polymorphic variables denoting objects from Node’Class and Encryptable’Class, respectively:
type Node_Class_Ref is access all Node'Class;
type Encryptable_Class_Ref is access all Encryptable'Class;
Next: Dynamic Dispatch
Inheritance in Ada is captured by type derivation, where a new tagged type (the derived type, corresponding to a subclass) is declared as an extension of an existing tagged type (the parent type, corresponding to the superclass). Type extension is as described in Part 1 of the series:
• All fields in the parent tagged type are present in the derived type
• New fields can be added in the extension part
• Primitive operations of the parent type are implicitly inherited unless overridden
• New primitive operations may be declared for the derived type
Ada supports single implementation inheritance and multiple interface inheritance. Thus a tagged type can inherit from at most one non-interface type and an arbitrary number of interface types. The types (parent tagged type, interface types) that the new tagged type is deriving from are referred to as the progenitors of the new type.
Here is an example of inheritance in Ada:
with Encryptable_Pkg;
with Ada.Strings.Unbounded;
package Node_Pkg.DataNode_Pkg is
type DataNode is new Node_Pkg.Node and Encryptable_Pkg.Encryptable with
-- extension part
record
Data : Ada.Strings.Unbounded.Unbounded_String;
end record;
overriding procedure Write (Item : in DataNode);
overriding procedure Read (Item : out DataNode);
overriding procedure Encrypt (Item : in out DataNode);
overriding procedure Decrypt (Item : in out DataNode);
end Node_Pkg.DataNode_Pkg;
The tagged type DataNode inherits from both the parent type Node and the interface Encryptable. Declaring DataNode_Pkg as a child of Node_Pkg—evidenced by the name Node_Packaging.DataNode_Pkg—allows the implementation of DataNode’s operations to access the representation of type Node in the private part of Node_Pkg. A DataNode object contains an Id field, from the parent type Node, and a Data field. The Get_Id and Set_Id procedures from Node are implicitly derived for DataNode with the signatures:
procedure Set_Id (Item : in DataNode; Id : in Integer);
function Id (Item : in DataNode) return Integer;
All the other procedures explicitly override the corresponding versions of the procedures for the tagged type Node and the interface Encryptable; the use of the reserved word overriding makes this intent clear. It is a compile-time error if a subprogram marked as overriding does not override a primitive operation of a progenitor type.
A subprogram parameter having a tagged type is always passed by reference. An inherited subprogram such as Set_Id or Id operates on an object of the derived type, but only has the parent type’s view of the object and thus can only access fields defined by the parent type.
An inheritance hierarchy rooted at a tagged type T, which may be an interface type, is denoted by the so-called class-wide type T’Class. An object of type T’Class is either an object of type T or else an object of some specific tagged type U that derives directly or indirectly from T. Polymorphism in Ada is generally modeled by a variable of an access type, or pointer, whose designated type is class-wide.
The following declarations define types for polymorphic variables denoting objects from Node’Class and Encryptable’Class, respectively:
type Node_Class_Ref is access all Node'Class;
type Encryptable_Class_Ref is access all Encryptable'Class;
Next: Dynamic Dispatch
Navigate to related information

