Child Packages
Child Packages
Child Packages - Motivation
- Problem Scenario - Imagine that:
- You want to add additional capability (eg size, clear) to intstackpkg
- But, you cannot modify intstackpkg.ads
- What the client wants:
s: stacktype;
...
put(size(s));
clear(s);
What's wrong with this:
procedure size(s: stacktype) is
begin
return s.thetop;
end size;
procedure clear(s: in out stacktype) is
begin
s.thetop := 0;
end size;
Where is it declared: client? package?
Solution: Create a child package
What is a Child Package?
- A child package is a package that ...
- ... has a parent package
- The child automatically has access to the (entire) parent specification.
Example: Child of the Stack Package
- Let's add this functionality to the Integer Stack Package:
- procedure put(s: stacktype);
- function toString(s: stacktype) return string;
- function size(s: Stacktype) return Integer;
- procedure clear(s: in out Stacktype);
- procedure reverseIt(s: in out Stacktype);
- function reverseIt(s: in Stacktype) return Stacktype;
- These routines might be useful to a client or for testing.
Code for Stack Package Child
Child Package Name
- A package declared like this:
package ppp.ccc is ...
is a child of package ppp
.
Package and File Names
- The specification for package
ppp.xxx
must be in file ppp-xxx.ads
- Rule: use a dash (ie "-") in place of the dot in the hierarchical name.
- The body for package
ppp.xxx
must be in file ppp-xxx.adb
Examples of Child Packages
Summary of What Child Packages Provide
- A child package provides a way to
- Put common types and routines in parent, to be shared by children
- Divide a set of routines and types into logically related subsets (ie sub-packages)
- Provides finer grain access to a set of routines (ie access to A and B, but not C
and D)
- Add new capability a package without modifying the parent
Visibility Issues
Logical Nesting
- The best way to think about accessibility of child package is logical nesting
- Logically nested means that it can be considered to be nested, even though it's not
really nested
- Consider the child to be logically nested in the parent (in terms of what
the child can see):
- The public section of the child's specification is logically nested in the
public section of the parent
- The private section of the child's specification is logically nested in the
private section of the parent
With Statements and Child Packages
-
with parent.child;
automatically does equivalent of with parent;
- Example:
with intstackpkg-utils;
procedure whatever is
s: intstackpkg.stack;
Okay to have with
for both child and parent. Example:
with intstackpkg;
with intstackpkg-utils;
If have parent and child, order does not matter:
with intstackpkg-utils;
with intstackpkg;
Use Statements and Child Packages
- Use - different from with - no connection of parent and child:
with intstackpkg-utils;
with intstackpkg; use intstackpkg;
procedure whatever is
s: stack; -- NO package name
i: Natural := intstackpkg-utils.size(s); -- package name required
Use - different from with - Another example:
with intstackpkg-utils; use intstackpkg-utils;
with intstackpkg;
procedure whatever is
s: intstackpkg.stack; -- package name required
i: Natural := size(s); -- NO package name
Accessibility
- The public section of the child's specification
can access the public section of the parent's specification,
- but not the private section of the parent's specification
- The private section of the child's specification and the body of the child
can access the
private section of the parent's specification.
- The child cannot access the body of the parent.
- Pseudo example:
-- specification
package ppp.ccc is
-- Can access public section of parent, but not private section
private
-- Can access public and private sections of parent
end ppp.ccc;
-- body
package body ppp.ccc is
-- Can access public and private sections of parent and child
end ppp.ccc;
More on Accessibility
- The parent has no access to its children (unless the parent with's the child)
- A child has no access to its siblings (unless it with's a sibling)
- When compiling a child, the compiler must be able to access the parent
- Can't create children of package Ada, or of its children
Benefits
Benefits of Child Packages
- Allows two (child) packages to share a private type (defined in parent)
- Example: Package Ada.Text_IO defines type File_Type, which is used by
Ada.Text_IO.Integer_IO and Ada.Text_IO.Float_IO (alternate names of
Ada.Integer_Text_IO, etc)
- Example: package Ada.Strings defines several types used by all strings
- type Direction is (forward, backward);
- Can put common operations in parent and less frequently used operations in a child
- Example: Ada.Text_IO has child package Ada.Text_IO.Text_Streams
(which provides a routine that gives stream access to a file)
- Provide additional capabilities to an existing package at a later time
- Provide another view of a package at a later time
- Example: Original navigation package provides locations as latitude and longitude
in degrees, minutes, and seconds. Child package later adds GPS
(degrees and decimal minutes)
- When a child adds new capabilities or views to an existing package:
- No need to modify working, tested package
- No recompilation of parent is necessary
- Helps avoid name clashes (ie namespace control):
- Example: All of the child packages in package Ada are separate from the
child packages in packages System and Interface and so their names are independent
- Programmers should not create packages named Ada or System or Interface
- Useful for unit testing
Another Example: Wordpkg
Child Package Word-Pals.adb
Private and Generic Child Packages
Private Child Packages
- We won't use private child packages, but FYI:
- The child specification is declared with keyword private
- A private child package is available to the siblings, but not to clients
Generic Child Packages
- Later we will learn about generic packages
- Here are some brief notes on creating child packages of generic packages