Section 6.7 - Private and Limited Private Types

If you simply declare types in a package specification in the way we've discussed so far, anyone who withs the package will be able to do anything to your new type that they could with the original types. In many cases this is bad, because these users (sometimes called clients or customers) will become dependent on the specific way the type was implemented. If the customers become dependent in this way, it will be very difficult to change the way the type is implemented (to improve performance, for example).

Ada provides several mechanisms to hide capabilities from customers. But first, it's important to understand the idea that, by removing capabilities, you gain more freedom. By removing capabilities from your customers, you (as the implementor of a type) gain more freedom to implement the type in any way that you choose. You also have more freedom to change the implementation later. Let's say that you declare a new type in a package specification in the way we've discussed so far. If you happen to base it on type Integer, your customers can still add, subtract, and so on. Even if you really want customers to only use the "less than" operation (as an "ordering" concept), the customers may not realize what limitations you had in mind and use all sorts of other operations that might not make sense in later revisions of the system. If you remove the ability to use the type as a normal Integer, the customers will be forced to use the type the way you intended -- and as a result you can change your implementation much more easily.

When declaring a type in a package declaration, you can declare the type as private. By declaring the type as "private" you disable the normal operations on that type (for example, "+" on Integers). After declaring a type as private, you then list the subprograms that you want to permit as publically-accessible operations on that type. If you declare a type as private, you must complete the type's definition in a section of the package declaration called the private part. If a type is declared as private, other packages can only use the operations that you provide and the assignment (:=) and equality (=) operations.

Here's an example. Let's say that you want to create a type called `Key', which uniquely identifies some resource; you only want people to be able to Request a key and determine if one key was requested before another (let's call that operation "<"). Here's one way to implement this (this example is inspired by the Ada RM section 7.3.1):

 package Keys is
   type Key is private;
   Null_Key : constant Key;         -- a deferred constant.
   procedure Get_Key(K : out Key);  -- Get a new Key value.
   function "<"(X, Y : in Key) return Boolean; -- True if X requested
                                                  -- before Y was
 private                                -- start package's private part.
   Max_Key  : constant := 2 ** 16 - 1;  -- A private constant.
   type Key is range 0 .. Max_Key;      -- Completed type definition.
   Null_Key : constant Key := 0;        -- Completed constant.
 end Keys;

Note that the type declaration in the package declaration is declared as `private'. This is later followed by the word `private' introducing the `private part' of the package specification. Here the type must be completely defined, as well as any constants necessary to complete its definition. Although Key is actually a numeric type, other packages cannot use addition, multiplication, and other numeric operations because Key is declared as `private' - the only operations are those defined in the package (as well as := and =).

Notice the function "<" in the example above. In Ada, you can redefine an infix operator such as "+", "*", and "<". The way to do that is to define the operation as a function taking two values, and using as the number name the operation inside double quotes. Notice also that you can create a constant value without saying exactly what its value is; you declare it as a constant with the given type, but don't actually give it its value; you then give the complete constant definition in the private part.

What if we don't want the default assignment (:=) and equals-to (=) operations? The answer: we declare the type as a limited private type instead of a private type. A limited private type is a private type that doesn't even define the default assignment and equals-to operations. Think of "limited" as an adjective on the word private. Here's how Key would be defined as a limited private type:

  type Key is limited private;

Quiz:

How would you define a type if you wanted only two operations on it called `up' and `down'?

  1. private
  2. limited private
  3. non-private

You may also:

PREVIOUS Go back to the previous section

NEXT     Skip to the next section

OUTLINE  Go up to lesson 6 outline

David A. Wheeler (dwheeler@dwheeler.com)

The master copy of this file is at "http://www.adahome.com/Tutorials/Lovelace/s6sf.htm".