Child packages provide another mechanism for breaking a complicated system into components. Here are some uses for child packages:
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.
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;
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.
![]() |
![]() |
---|
David A. Wheeler (dwheeler@ida.org)
The master copy of this file is at "http://www.adahome.com/Tutorials/Lovelace/s15sf.htm".