Previous Table of Contents Next


Defining, in this fashion, additional meanings for the existing operator symbols is called operator overloading. Ada allows you to overload any of the existing operator symbols and prohibits you from defining any new operator symbols.

In this interface, I have documented the various groups of operations with comments indicating preconditions and postconditions. These lie outside Ada but are increasingly commonly used in Ada and other languages to give concise and consistent descriptions of sets of operations. The precondition (line 9)

   -- Pre :   X and Y are defined

indicates that the behavior of this operation can be assured only if the client program refrains from passing it uninitialized variables. In Ada, variables are not initialized by default and there is no requirement that the programmer provide initialization expressions in declarations. Moreover, there is, in general, no assured compile-time or runtime check that variables are initialized. The precondition is therefore very important in Ada: As in most programming languages, initialization is a programmer responsibility.

The postcondition

   -- Post:   returns a rational number
   --   If Y > 0, returns X/Y
   --   If Y < 0, returns (-X)/(-Y)
   -- Raises: ZeroDenominator if Y = 0

describes the behavior of the “/” operator in succinct terms. Lines 15-38 declare a full set o‹f operations on ration quantities; their intent is obvious from their declarations and postconditions.

Line 21

   function “=” (R1, R2 : Rational) return Boolean;

merits a bit of discussion. The equality-test operation is predefined in Ada for most types, including private ones. Here I override the predefined equality test because it may give incorrect results. Predefined equality compares its two operands bitwise; any disagreement yields a False result. Algebraically, 1/3 = 2/6 = 24/72, and so on. Ada’s predefined equality would return False if applied to 1/3 and 2/6. I need my own equality test, so I provide it in the package interface and deliver it in the package body I examine shortly.

I defined all the operators as functions because, in fact, mathematically an operator is just a function with certain restrictions on its arguments. Indeed, the standard defines the operators on the predefined types using just this function syntax.

10.4.2.3. A Child Package for Rational Input and Output

To provide clients with an easy way to input and display rationals, I provide a child package HB.Rationals.IO, in which Get and Put operations are provided for the standard and named input and output files. There is no requirement that this package be a child of Rationals; I simply chose to make it so.

    1 with Ada.Text_IO;
    2 use Ada.Text_IO;
    3 package HB.Rationals.IO IS
    4
    5   procedure Get (Item : out Rational);
    6   procedure Get
    7     (File: in File_Type; Item : out Rational);
    8
    9   procedure Put (Item : in Rational);
   10   procedure Put
   11     (File: in File_Type; Item : in Rational);
   12
   13 end HB.Rationals.IO;

In this package interface, note how the various procedure parameters are specified. In writing Ada procedures, you choose a mode for each parameter. That is, you declare each parameter as in, out, or in out; in the absence of a mode specifier, in is specified by default.

Ada separates the intended use of parameters from the mechanism by which they are passed. An in parameter is treated as a constant, or read-only value, within the body of the procedure. Because no code within the procedure can attempt to modify an in parameter—this is, of course, checked by the compiler—it is of no concern whether the parameter is passed by copy or by reference.

In fact, the Ada standard requires that scalar parameters be passed by value; an in out scalar is copied from actual to formal at the start of a procedure execution, and the possibly new value is copied back from formal to actual at procedure completion. On the other hand, composite (record and array) parameters can be legally passed either by copy or by reference; most compilers pass them by reference.

Parameters or functions must be in; programmers generally omit the explicit in from function parameter declarations, and I have omitted it in the packages here.


Previous Table of Contents Next