Section 15.2 - Child Packages

Ada 95 has added a new capability called a "Child Package." A child package is a package that is conceptually part of its parent package, but a child package can be compiled separately (after its parent has been compiled) without recompiling or modifying the parent.

Child packages provide another mechanism for breaking a complicated system into components. Here are some uses for child packages:

  1. You can put "normal" operations in a package, and "special" operations that not everyone should use in a child package. That way, most customers will see the normal operations and only be able to use the "special" operations if they specifically request them.
  2. You can create a new set of operations in a child package without changing the parent package. That means that you don't have to recompile the parent package or anything that depends on the parent package, reducing recompilation time.

Child packages are especially useful if you define a private tagged type in a package. A child package can "see" the definition of a private tagged type, because conceptually the child package is part of the parent package. As a result, a child package can use ``inside information'' not available to just any package. Use this capability with care; don't abuse it.

We'll go over child packages briefly here, but feel free to skim this section and return later if you like.

To understand how child packages work, let's first repeat the fundamentals. Any package can have a declaration (specification) and a body, and the package declaration can have both a public part and a private part. Normally the private part of the package declaration can only be seen by the body of package X; anyone who "with"s package X may only see the public part.

A child package adds a few twists. First, a child package is considered to have "automatically with'ed" its parents. In the public part of a child package you can only see the public part of your ancestors, just as though the package had the statement "with Parent" at the top. The real difference, though, is what happens in the child package declaration (specification) private part and body - in those places, the private part of the child packages' ancestors are made visible. That's an important difference - normally packages do not at any time have visibility to the private parts of other packages.

Let's go through an example to make this clearer. Let's say you have a package named "X". Package X can have a declaration (specification) and a body. Package X's declaration can have a public part and a private part. Normally only package X's body can see the private part of the package declaration; anyone who "with"s package X may only use the public part.

[Child Package] Now, let's define a child package of X, called "X.Y". Package X.Y's public part can see the public part of X automatically, and the private part of X.Y and the body of X.Y can automatically see the private part of package X. This isn't considered a violation of Ada's safety rules, because X.Y is considered to be part of X.

The syntax for declaring a child package is the same as ordinary packages, you just name the child package using dotted notation:

  package X.Y is ....
  end X.Y;

[Private Child Package] You can also have private children (the normal kind of children are called public children). Private children are intended for "internal" packages that should only be "with'ed" by a restricted number of packages. Private children can only be "with'ed" by the body of its parent or by descendents of the private child's parent. In exchange for such a restrictive requirement, a private child gets a new authority: a private child's specification automatically sees both the public and private parts of all of its ancestors' specifications. To declare a private package, just prepend the word "private":

  private package X.Z is ....
  end X.Z;

You can with a child package by specifying its parents in dotted notation. Whenever you name a child package in a "with" statement, you automatically "with" all of its ancestors. For example, if package "Ada" has a child package named "Strings", which then has a child package named "Unbounded", you would say:

  with Ada.Strings.Unbounded;

When you "with" Ada.Strings.Unbounded, you automatically "with" the packages "Ada" and "Ada.Strings". That doesn't mean that you automatically "use" them; you can then "use" whichever packages you wish.

There's a lot more about child packages that we won't cover now. The Ada Rationale section II.7 describes child packages (also called hierarchical libraries) in more detail if you are curious.


There is no quiz question for this section.

You may go to the next section.


You may also:

PREVIOUS Go back to the previous section

OUTLINE  Go up to the outline of lesson 15

David A. Wheeler (dwheeler@dwheeler.com)

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