The guidelines encourage much code to be written to ensure strong typing (i.e., subtypes). While it might appear that there would be execution penalties for this amount of code, this is usually not the case. In contrast to other conventional languages, Ada has a less direct relationship between the amount of code that is written and the size of the resulting executable program. Most of the strong type checking is performed at compilation time rather than execution time, so the size of the executable code is not greatly affected.
Language Ref Manual references: 3 Declarations and Types
In this section... 5.3.1 Derived Types and Subtypes 5.3.2 Anonymous Types 5.3.3 Private Types |
Summary of Guidelines from this section |
Table
is a building block for the creation of new types:
type Table is record Count : List_Size := Empty; List : Entry_List := Empty_List; end record; type Telephone_Directory is new Table; type Department_Inventory is new Table; |
The following are distinct types that cannot be intermixed in operations that are not programmed explicitly to use them both:
type Dollars is new Number; type Cents is new Number; |
Below, Source_Tail
has a value outside the range of Listing_Paper
when the
line is empty. All the indices can be mixed in expressions, as long as the
results fall within the correct subtypes:
type Columns is range First_Column - 1 .. Listing_Width + 1; subtype Listing_Paper is Columns range First_Column .. Listing_Width; subtype Dumb_Terminal is Columns range First_Column .. Dumb_Terminal_Width; type Line is array (Columns range <>) of Bytes; subtype Listing_Line is Line (Listing_Paper); subtype Terminal_Line is Line (Dumb_Terminal); Source_Tail : Columns := Columns'First; Source : Listing_Line; Destination : Terminal_Line; ... Destination(Destination'First .. Source_Tail - Destination'Last) := Source(Columns'Succ(Destination'Last) .. Source_Tail); |
Define new types, derived types, and subtypes cautiously and deliberately. The concepts of subtype and derived type are not equivalent, but they can be used to advantage in concert. A subtype limits the range of possible values for a type, but does not define a new type.
Types can have highly constrained sets of values without eliminating useful values. Used in concert, derived types and subtypes can eliminate many flag variables and type conversions within executable statements. This renders the program more readable, enforces the abstraction, and allows the compiler to enforce strong typing constraints.
Many algorithms begin or end with values just outside the normal range. If boundary values are not compatible within subexpressions, algorithms can be needlessly complicated. The program can become cluttered with flag variables and special cases when it could just test for zero or some other sentinel value just outside normal range.
The type Columns
and the subtype Listing_Paper
in the example above
demonstrate how to allow sentinel values. The subtype Listing_Paper
could be
used as the type for parameters of subprograms declared in the specification
of a package. This would restrict the range of values which could be
specified by the caller. Meanwhile, the type Columns
could be used to store
such values internally to the body of the package, allowing First_Column - 1
to be used as a sentinel value. This combination of types and subtypes allows
compatibility between subtypes within subexpressions without type conversions
as would happen with derived types.
Language Ref Manual references: 3.3.2 Subtype Declarations, 3.4 Derived Types, 3.5 Scalar Types
type Buffer_Index is range 1 .. 80; type Buffer is array (Buffer_Index) of Character; Input_Line : Buffer; |
rather than
Input_Line : array (Buffer_Index) of Character; |
Even though the implicit conversion of array types during parameter passing is supported in Ada, it is difficult to justify not using the type of the parameter. In most situations, the type of the parameter is visible and easily substituted in place of an anonymous array type. The use of an anonymous array type implies that the array is only being used as a convenient way to implement a collection of values. It is misleading to use an anonymous type and then treat the variable as an object.
In reading the Ada Language Reference Manual (Department of Defense 1983), you will notice that there are cases when anonymous types are mentioned abstractly as part of the description of the Ada computational model. These cases do not violate this guideline.
Language Ref Manual references: 3.6 Array Types
------------------------------------------------------------------------ package Packet_Telemetry is type Frame_Header is limited private; type Frame_Data is private; type Frame_Codes is (Main_Bus_Voltage, Transmitter_1_Power); ... private type Frame_Header is record ... end record; type Frame_Data is record ... end record; ... end Packet_Telemetry; ------------------------------------------------------------------------ |
Limited private types have the most restricted set of operations available to
users of a package. Of the types that must be made available to users of a
package, as many as possible should be limited private. The operations
available to limited private types are membership tests, selected components,
components for the selections of any discriminant, qualification and explicit
conversion, and attributes 'Base
and 'Size
. Objects of a limited private type
also have the attribute 'Constrained
if there are discriminants. None of these
operations allow the user of the package to manipulate objects in a way that
depends on the structure of the type.
If additional operations must be available to the type, the restrictions may be loosened by making it a private type. The operations available on objects of nprivate types that are not available on objects of limited private types are assignment and tests for equality and inequality. There are advantages to the restrictive nature of limited private types. For example, assignment allows copies of an object to be made. This could be a problem if the object's type is a pointer.
Language Ref Manual references: 7.4 Private Type and Deferred Constant Declarations, 7.4.1 Private Types, 7.4.4 Limited Types, 12.3.2 Matching Rules for Formal Private Types, A Predefined Language Attributes