


                                                        Chapter 7
                                                    DERIVED TYPES


LET'S TALK ABOUT TYPES
_________________________________________________________________

We have been talking about types throughout this tutorial, but
we've been sort of working our way around them rather than
carefully defining the various kinds of types available in Ada.
This chapter will be devoted to a full discussion of types.  It was
not possible to discuss types in full until we covered a bit of
material about the various scalar types and how they are used, but
with that material behind us, we will give a full treatment to the
topic of types.

There are four different ways to declare a type.  You can probably
guess that we will discuss each of the ways in detail in this
chapter.  They are listed as follows;

1.   Predefined types.  These are provided for us by the compiler
     writer as defined in the LRM.  We have already used several
     of these.

2.   User defined types.  We have already defined a few new types
     in some of the earlier programs.

3.   Derived types.  These get their name because they are defined
     in part based on a previously defined type and derive some of
     their characteristics from those types.  We have not yet
     encountered the derived type.

4.   Subtypes.  These are usually a subset of another type upon
     which they are based.  We encountered subtypes in the last
     chapter.

Before we launch into a detailed definition of these four type
definition methods, we must devote a little attention to the
various type classes.



TYPE CLASSES IN ADA
_________________________________________________________________

There are five type classes in Ada, a class being a rough grouping
of types because of similar characteristics.  The five type classes
and a brief definition of each is given below.

Scalar class - This includes all of the types we have used so far
       in this tutorial, and are characterized by the fact that each
       variable of this class can store a single number, either
       variable or constant.  Discrete types are a subset of this

                                                         Page 7-1

                                        Chapter 7 - Derived Types

       class and include all integer types, enumerated types, and
       the CHARACTER type.  All real types are included in the scalar
       class, but not the discrete subclass.  The remainder of this
       chapter will utilize scalar class variables as examples of the
       various type definition methods.

Composite class - This class includes the array types and the
       record types.

Access class - Variables of this type are similar to the pointer
       type in Pascal or C, and are used to access a variable or
       group of variables in an indirect manner.

Private class - This class of types is used for information hiding
       techniques when used on a multi-programmer project.

Tasking class - This type class is used for concurrent processing.

All of these classes will be illustrated in detail later in this
tutorial.  The concept of typing is one of the most important in
Ada, because the proper use of typing will act as a tremendous aid
in locating programming errors.  Keep in mind that all types are
static and cannot be changed during program execution.



PREDEFINED TYPES IN ADA
_________________________________________________________________

The LRM requires every Ada compiler to provide several predefined
types, including INTEGER, NATURAL, POSITIVE, FLOAT, CHARACTER, and
STRING.  Several other types are optional and include LONG_INTEGER,
SHORT_INTEGER, LONG_FLOAT, and SHORT_FLOAT.  It will be left to you
to study the documentation that came with your compiler and see
which of the optional types are included with your compiler
package.

The predefined types can be used as the basis of the declaration
of new types for your specific application and is the topic of this
chapter.



USER DEFINED TYPES
_________________________________________________________________

Examine the program named DERTYPES.ADA for       ================
several examples of user defined types.  Lines     DERTYPES.ADA
10 through 12 each declare an entirely new type. ================
Considering the predefined type INTEGER and
these three, we actually have four types to use
in the program, and each type has nothing to do with the other
three.  Variables of these types cannot be intermixed in any way
without the proper type conversion explicitly stated by the

                                                         Page 7-2

                                        Chapter 7 - Derived Types

programmer.  Moreover, variables declared with one of these types
cannot be assigned a value that is outside of its declared range.
The structure for declaring a user defined integer class type is
given as,

     type <type-name> is range <lower-limit>..<upper-limit>;

As stated earlier, the word range is a reserved word, and its
presence indicates to the compiler that you wish to have a type of
the integer class.

Use of the three new types is not illustrated in this example
program, but the diligent student will have no trouble using these
new types to declare a few variables, then use them in some
mathematical statements.



DERIVED TYPES ARE RELATIVELY NEW
_________________________________________________________________

Derived types are an entirely new subject, since they are not
available in any of the more popular languages that you may have
been programming in.  Derived types get their name because they are
derived from an existing type rather than being an entirely new
creation.  A derived type has all of the operations available that
are available with the parent type but it may have a more limited
range than the range of the parent type.  The example program has
as illustration of this in line 13 where the type TINY_POS is
derived from the user defined type POS_INT but with a slightly
tighter allowable range.

Any operation that is legal to be performed on a variable of type
POS_INT is legal for a variable of type TINY_POS.  In fact, if we
would have declared a subprogram (which we haven't studied yet),
prior to line 13, that operated on variables of type POS_INT, then
that same subprogram could be used for variables of type TINY_INT.
We will have more to say about this when we get to the chapter on
subprograms in this tutorial.

The key to a derived type is the use of the reserved word new along
with the type from which the new type will be derived.  The
structure for declaring a user defined derived type is given as,

     type <type-name> is new <existing-type> <optional-range>;

The derived type will be of the same class as the type from which
it is derived, in this case it will be of the integer type class.

We continue declaring new types in lines 14 through 16 and because
these three are entirely new types, each derived from the parent
type INTEGER, they cannot be added together, subtracted, compared
or even assigned to each other without a bit of extra trouble.
Each of the seven new types in lines 10 through 16 share all of

                                                         Page 7-3

                                        Chapter 7 - Derived Types

the operations that are defined for INTEGER, including the
arithmetic, logical, and assignment operations, but the operations
can only be performed as long as the types of the objects are
consistent.  Of course, the explicit type conversion can be done
to allow the combination of variables of any of these types.

The type TREE_INT, defined in line 16, is a derived type with a
more limited range than the parent type so it has all of the
characteristics of the parent type except that it cannot be
assigned a value outside of its defined range.



HOW TO USE SOME OF THE NEW TYPES
_________________________________________________________________

As an example of using the new types, consider the type SALAD_INT
which is a derived type of the parent type INTEGER.  Since three
variables, Salad, Lettuce, and Tomatoes, are all of the same type,
they can be freely added, compared, assigned to each other, or used
in any way legal for integer class variables.  They can be used as
the iteration index or range limits in a for loop.  The three
variables have the same range as the parent type INTEGER, namely
-32768 to 32767 on most 16 bit machines.  Constants of type
universal_integer can be added to, compared to, or assigned to
these three variables, as well as any of the other variables
declared in this program.



HOW CAN THESE NEW TYPES HELP IN A PROGRAM?
_________________________________________________________________

Everything that was said about type SALAD_INT in the last paragraph
is true of type ANIMAL_INT, TREE_INT, or any of the other four
types.  Suppose somewhere in our program we tried to add the number
of Tomatoes to the number of Dogs and assign the result to Trees.
If the variable names are meaningful, we would probably not want
to do such an operation in any practical program.  The Ada compiler
would give us a compile time error, so we would detect the error
before we tried to run the program with such a silly statement.
Careful assignment of types can be used to protect us from the
silly little errors that we are all so prone to make.  It would be
much more efficient to let the compiler find these silly little
errors and free us up to find the analysis errors we also make.



HOW DO YOU DO A TYPE TRANSFORMATION?
_________________________________________________________________

Even though you set things up very carefully, you may need to
perform some operations on the data where you actually do need to
add the number of Animals to the total of Oak plus Coconut.  Line

                                                         Page 7-4

                                        Chapter 7 - Derived Types

33 illustrates how to do this.  Enclosing the variable in
parentheses and adding the desired type to the front of the
grouping will change the type from the variable's actual type to
the type in front of the parentheses, but only for that one place
in the program.  If you want to use the type transformation again,
you add the type in front of the variable again.

In line 34, Trees and Salad are both transformed to type INTEGER
before being summed and assigned to Count, a variable of type
INTEGER.  Line 36 illustrates the addition of many variables by
first transforming each to type SALAD_INT then performing the
addition.  In line 43, the same variables are added together, but
in this case, all variables are transformed into type ANIMAL_INT
prior to summing, then the sum is transformed to type SALAD_INT.
The two methods should result in the same answer, and you can
verify that they do when you compile and run the program.



WHAT IS A SUBTYPE?
_________________________________________________________________

A subtype is a new type based on a parent type but usually with a
more restricted range.  It inherits all of the characteristics of
the parent type and in addition, it can be freely intermixed with
the parent type in calculations and assignment statements.  The
reason for using a subtype is usually to declare a variable of the
parent type but with a more limited range to take advantage of the
range checking capability of Ada.



WE CAN ALSO HAVE SUBTYPES OF DERIVED TYPES
_________________________________________________________________

The program named DERSUBS.ADA gives an example    ===============
of the definition and use of a subtype of a         DERSUBS.ADA
derived type, and a derived type of a subtype.    ===============
In line 10 we declare a derived type and in line
13 we declare a subtype of the new derived type.
The subtype of the derived type has the same characteristics as
the derived type except that it has a more restricted range in this
case.  Variables of type NEW_SUBTYPE are compatible with variables
of their parent type NEW_INT.  This is illustrated in line 29.

In this case, NEW_SUBTYPE is as different from the type INTEGER,
as SALAD_INT was in the last program.


WE CAN HAVE A DERIVED TYPE OF A SUBTYPE
_________________________________________________________________

Line 15 illustrates the declaration of a derived type based on
using a subtype for the parent type.  Note that the new derived

                                                         Page 7-5

                                        Chapter 7 - Derived Types

type has all of the characteristics of its parent type except for
the more restricted range, but once again, it is an entirely new
type as far as type checking is concerned.



A SUBTYPE CAN BE SIMPLY A SYNONYM
_________________________________________________________________

Line 13 illustrates a subtype which covers the entire range of its
parent type.  Since variables of this subtype can be freely
intermixed with variables of its parent type, the subtype name is
simply a synonym for the parent type name.

With the discussion of the last program fresh in your mind, you
should breeze through the remainder of this program.  Be sure to
compile and execute it.



USING OTHER PREDEFINED TYPES FOR THE PARENT
_________________________________________________________________

Examine the program named MOREDERS.ADA for       ================
examples of derived types and subtypes based on    MOREDERS.ADA
some of the other predefined types in Ada.  We   ================
begin by declaring two user defined types in
lines 8 and 9 which are of the floating point
class of types because of the reserved word digits appearing in the
definition.  In line 10 we declare DER_FLOAT which has all of the
characteristics of the predefined type FLOAT, except that the
compiler will consider it to be an entirely different type and will
not allow mixing of these two types.  Of course, type conversion
can be used if necessary.

The derived type LIM_FLOAT is declared with all the characteristics
of FLOAT except that it has a limited range to allow for compiler
checks.  Line 12 contains the definition of a subtype based on
DER_FLOAT with a more limited range.  Variables of the type
SUB_FLOAT can be freely intermixed with variables of type
DER_FLOAT, but not with those declared with the types FLOAT,
NEW_FLOAT1, NEW_FLOAT2, or LIM_FLOAT.

Lines 15 through 19 illustrate the same principles applied to fixed
point types and should be self explanatory.  The only difference
is the use of the reserved word delta in the fixed point
definitions.

Lines 22 through 29 illustrate the declaration of derived types and
subtypes of the CHARACTER type and an enumerated type.  These
statements will be left to the students study since they are so
similar to the example using FLOAT as the parent type.



                                                         Page 7-6

                                        Chapter 7 - Derived Types

A few variables are declared and some are initialized in lines 32
through 35, and a nonsense calculation is given in line 39 to
illustrate the type transformations that can be done with derived
types.

Be sure to compile and execute this program even though it has no
output.



A WORD OF SUMMARY ABOUT TYPES
_________________________________________________________________

We have seen that in addition to the predefined types, we can
declare additional types for use in our programs.  We can then use
any of the predefined or user defined types as the parent type for
either subtypes or derived types.  The new subtype or derived type
can be used as a parent type for additional subtypes or derived
types and we find that we have a tremendous amount of flexibility
in defining the data to solve any particular problem.



PROGRAMMING EXERCISE
_________________________________________________________________

1.   Modify the program named DERTYPES.ADA to include a new
     instantiation of the package Text_IO.Integer_IO to output the
     variable named Salad in line 40 and 47 without the type
     conversion.
























                                                        Page 7-7

