[ Table of Contents ]
Here is a better way to construct the basketball scoreboard subsystem of the previous example. We use child units (not available in Ada 83), which allow us to develop the subsystem using multiple separate modules rather than one large package with multiple nested parts. This kind of construction is often referred to as the hierarchical library feature of Ada. There are two kinds of child units: public and private. The former can be accessed (withed in) by any other unit. The latter can be accessed only by other members of its own "family."
This diagram depicts a parent package named Score and two public child library packages named Score.Events and Score.Display. Ultimately, different client modules would call subprograms exported by these two children. Note the two different kinds of relationships depicted -- withing relationships and parent/child relationships. |
Uses of Child Units
Here is a quotation taken from Section 10.10 of [Cohen96].
"Child units have several important uses including the following:
Source Code Listing
------------------------------------------------------------ -------------------------- Score --------------------------- -- This parent library package exports two enumeration -- types and provides several private types, which are -- accessible by its children. It needs no body. ------------------------------------------------------------ package Score is type Player_Name is (Adam, Bill, Carl, Dave, Eric, Fred, Glen, Hank, Ivan, John); type Shot_Type is (Foul_Shot, Two_Pointer, Three_Pointer); private Home_Score : Natural := 0; Visitors_Score : Natural := 0; Foul_Status : array (Player_Name'Range) of Natural := (Player_Name'Range => 0); subtype Home_Player is Player_Name range Adam..Eric; subtype Visiting_Player is Player_Name range Fred..John; end Score; ------------------------------------------------------------ ----------------------- Score.Events ----------------------- -- This child package exports two procedures, which handle -- two kinds of events: shots made and fouls committed. ------------------------------------------------------------ package Score.Events is procedure Shot_Made (By : in Player_Name; Shot : in Shot_Type); procedure Foul_Committed(By : in Player_Name); end Score.Events; ------------------------------------------------------------ with Ada.Text_IO; use Ada.Text_IO; package body Score.Events is procedure Shot_Made(By : in Player_Name; Shot : in Shot_Type) is Points : Integer range 1..3; begin if Shot = Foul_Shot then Points := 1; elsif Shot = Two_Pointer then Points := 2; elsif Shot = Three_Pointer then Points := 3; end if; if By in Home_Player'Range then -- membership test Home_Score := Home_Score + Points; elsif By in Visiting_Player'Range then -- membership test Visitors_Score := Visitors_Score + Points; end if; end Shot_Made; ----------------------------------------------- procedure Foul_Committed(By : in Player_Name) is begin Foul_Status(By) := Foul_Status(By) + 1; end Foul_Committed; ----------------------------------------------- end Score.Events; ------------------------------------------------------------ ----------------------- Score.Display ---------------------- -- This child package exports two procedures, which handle -- two kinds of display requests. ------------------------------------------------------------ package Score.Display is procedure Show_Scores; procedure Show_Fouls; end Score.Display; ------------------------------------------------------- with Ada.Text_IO; use Ada.Text_IO; package body Score.Display is procedure Show_Scores is begin New_Line; Put_Line("Score: Home " & Integer'Image(Home_Score) & " Visitors " & Integer'Image(Visitors_Score)); New_Line; end Show_Scores; ------------------------------------------ procedure Show_Fouls is Name : Player_Name; begin Put_Line("Home Team Fouls:"); for Name in Home_Player'Range loop Put(" "); Put(Player_Name'Image(Name)); Put(Integer'Image(Foul_Status(Name))); end loop; New_Line; Put_Line("Visiting Team Fouls:"); for Name in Visiting_Player'Range loop Put(" "); Put(Player_Name'Image(Name)); Put(Integer'Image(Foul_Status(Name))); end loop; New_Line; end Show_Fouls; ------------------------------------------ end Score.Display; ------------------------------------------------------------ ------------------------Test_Score ------------------------- -- This test procedure sends a sequence of messages to the -- Score.Events package involving shots made and fouls -- committed, and messages to the Score.Display package -- requesting display of data. ------------------------------------------------------------ with Score.Events; with Score.Display; use Score; procedure Test_Score is begin Score.Display.Show_Scores; Score.Display.Show_Fouls; Score.Events.Shot_Made (By => Bill, Shot => Two_Pointer); Score.Events.Foul_Committed(By => Carl); Score.Events.Shot_Made (By => Hank, Shot => Foul_Shot); Score.Events.Shot_Made (By => Dave, Shot => Three_Pointer); Score.Events.Shot_Made (By => Fred, Shot => Two_Pointer); Score.Events.Foul_Committed(By => Glen); Score.Events.Shot_Made (By => Eric, Shot => Foul_Shot); Score.Display.Show_Scores; Score.Display.Show_Fouls; end Test_Score; ------------------------------------------------------------ |
The above program produces exactly the same output as the program in the previous example on nested units.
Related Topics
[ Back to top of page ]