



Abstract Data Type





	Definition #1: (from the text) A class of data objects with a defined set of properties and a set of operations that 
process the data objects while maintaining the properties.

	Definition #2: A set of values and a set of operations on those values.

	Many basic data types satisfy these definitions.

	Example #1: The Ada type Integer.

	Values: 0, 1, -1, 2, -2, etc.	Operations: +, -, *, /, etc.





	Example #2: The Ada type Float.

	Values: 0.0, 0.1, 1.2, -3.245, etc.	Operations: +, -, *, /, etc.





	Example #3: The Ada type String.

	Values: "a", "xyz", "abc123", etc.	Operations: &, indexing, assignment, input, output, etc.





Abstract Data Type, Cont.





	Example #4: Consider the following record type declaration.



	type Person_Rec is

		record

			Name : String (1..32);

			Age : Natural;

			Height : Float;

			Weight : Float;

		end record;





	Values:

		("Bob", 34, 65.5, 155.3)

		("Sue", 25, 62.0, 112.5)

		("Joseph", 14, 55.3, 115.3)

			:

			:



	Operations:

		=, <>, :=, field referencing, etc.





An Abstract Data Type - List



	Until now, all "lists" have been stored in arrays.

	Lists can, and will, be stored in other ways, for a variety of reasons.

	Consequently, it is useful to define the notion of a "list" abstractly, independent of any particular implementa-
tion.

	Definition: A list is a varying length linear collection of components that are ordered and homogenous.

		Linear - A one dimensional collection of elements.



		Homogenous - Every element in the list is of some base type (which may itself be an abstract type).



		Ordered - Every list has a first component, a last component, every element has a predecessor (except the first), and every ele-
ment has a successor (except the last).



	Operations: (in reality, this list is incomplete)

		Add	Add an item to the list.

		Clear	Delete all elements in the list.

		Full	Returns "true" if it is not possible to add another element to the list.

		Length	Determine and return the length of the list.

		Retrieve	Return a copy of the element at a particular position in the list.

		Search	Return the position of the element in the list that is identical to element e.





Abstract Data Type Operations





	In general, abstract data type operations fall into (approximately) five different categories:

Constructors - Create a new instance of an abstract data type. Typically allocates and initializes memory.



Destructors - Deletes an existing instance of an abstract data type.  Typically deallocates memory.



Modifiers - Modifies an instance of an abstract data type.



Observers - Operations that allow us to observe the state of an instance of an abstract data type without changing it.



Iterators - Operations that allow us to process all of the components in an abstract data type.







	Note that the book provides only three categories:

Constructors - Operations that alter the state of an instance of an abstract data type.



Observers - As above.



Iterators - As above.





Abstract Data Type Operations





	Using the books definitions:

Constructors - Add, Clear



Observers - Length, Full, Retrieve, Search





	Using the other definitions:

Modifier - Add, Clear (note that Clear is not a destructor).



Observers - Length, Full, Retrieve, Search





	Question: Why talk about data structures and functions/procedures in such abstract terms?

Software design is often language independent.



Languages dictate syntax primarily.



Design dictates logic and structure, which are expressed as ADTs.







An Abstract Data Type for a List of Students





package Student_Types is



		-- Types for student record

		type Letter_Grade_Type is (A, B, C, D, F);

		subtype ID_Type is Integer range 0..9999;

		subtype Percent is Integer range 0..100;

		subtype GPA_Type is Float digits 4 range 0.00..4.00;

		subtype Name_String is String (1..15);



		-- The student record

		type Student_Rec is

			record

				Student_ID						: ID_Type;

				First_Name						: Name_String;

				Last_Name						: Name_String;

				GPA						: GPA_Type;

				Program_Grade						: Percent;

				Quiz_Grade						: Percent;

				Final_Exam						: Percent;

				Course_Grade						: Letter_Grade_Type;

			end record;



end Student_Types;





An Abstract Data Type for a List of Students





with Student_Types;

package Student_List is



	-- This package contains the types and operations necessary for an

	-- unordered list of student records



	-- Constants

	Max_Length: constant := 100;  -- The maximum number of student records in a list



	-- Unconstrained array for list parameters

	subtype Item_Type is Student_Types.Student_Rec;  -- List components are Student records

	type Item_Array is array (Integer range <>) of Item_Type;



	-- Constrained array for list variables

	subtype Index_Type is Integer range 1..Max_Length;

	subtype Length_Type is Integer range 0..Max_Length;

	subtype List_Array is Item_Array(Index_Type);



	type List_Type is   -- A list of Student records

		record

			Length : Length_Type := 0;								-- The number of components in the list

			Items : List_Array;								-- The components

		end record;





An Abstract Data Type for a List of Students, Cont.





	------------------------------

	-- List constructor operations

	------------------------------



	----------------------------------------------------------------------------

	procedure Clear_List (List : in out List_Type);   -- The list to create



	-- This procedure creates an empty list

	--

	-- Preconditions     None

	--

	-- Postconditions    List contains no elements; it is empty



	----------------------------------------------------------------------------

	procedure Add (					Item : in Item_Type;								-- The item to add to the list

						List : in out List_Type);								-- The list



	-- This procedure adds the given item to the end of the given list

	--

	-- Preconditions     The list is not full

	--

	-- Postconditions    Item is added to the end of List





An Abstract Data Type for a List of Students, Cont.





	---------------------------

	-- List observer operations

	---------------------------



	----------------------------------------------------------------------------

	function Length (List : in List_Type) return Natural;



	-- This function returns the number of elements currently in the list

	--

	-- Preconditions      None

	--

	-- Postconditions    The number of elements currently in the list is returned



	----------------------------------------------------------------------------

	function Full (List : in List_Type) return Boolean;



	-- This procedure determines whether any more items can be added to the list

	--

	-- Preconditions      None

	--

	-- Postconditions    False is returned if there is space in the list for another item.

	--                             Otherwise, True is returned





An Abstract Data Type for a List of Students, Cont.





	----------------------------------------------------------------------------

	procedure Retrieve (						List :  in List_Type;								-- List from which to retrieve

							Position :  in Index_Type;								-- The position of the desired item

							Item : out Item_Type);								-- The retrieved item



	-- This procedure retrieves a copy of an item in the list

	--

	-- Preconditions      Position is not greater than the length of the list

	--

	-- Postconditions    Item is a copy of the list element at Position

	--                             The list is not changed



	----------------------------------------------------------------------------

	procedure Search (						List :  in List_Type;										-- List to be searched

							ID : in Student_Types.ID_Type;										-- The ID of the desired item

							Position : out Index_Type;										-- Location of the item, if found

							Found : out Boolean);										-- True if ID is found in the list



	-- This procedure searches a list for a student record with the given ID

	--

	-- Preconditions      None

	--

	-- Postconditons     If the ID is found in the list, Found is True and Postion gives the location

	--                             Otherwise, Found is False and Position is List.Length + 1.



end Student_List;





Example Main









with Integer_IO;							-- Preinstantiated I/O package

with Student_Types;

with Student_IO;

with Student_List;

with Text_IO;



procedure Example is

	ID_Number 					: Student_Types.ID_Type;								-- The ID number of a student

	Student_Info					: Student_List.Item_Type;								-- Information for one student

	Student_In_List					: Boolean;								-- Flag for list searchs

	Location					: Student_List.Index_Type;								-- Position of a student in a list



	Class_Code					: Character;   



	-- List variables for the classes

	Biology_Class					: Student_List.List_Type;

	Geology_Class					: Student_List.List_Type;





Example Main, Cont.



begin  -- Example



	-- Get student information for each student and add to proper list

	-- It is assumed that no class has more students than can be stored on a class list

	Input_Loop:

	loop

			:

		Text_IO.Get (Class_Code);

		Student_IO.Get (Student_Info);

		if Class_Code = `B' then

			Student_List.Add (Item => Student_Info, List => Biology_Class);

		elsif Class_Code = `G' then

			Student_List.Add (Item => Student_Info, List => Geology_Class);

		end if;

			:

	end loop Input_Loop;



	-- Print the ID numbers and last names of the students in the Geology Class

	for Index in 1..Student_List.Length (Geology_Class) loop

		Student_List.Retrieve (							List => Geology_Class,

									Position => Index,

									Item => Student_Info);

		Integer_IO.Put (Item => Student_Info.Student_ID, Width => 5);

		Text_IO.Put_Line ("   " & Student_Info.Last_Name);

	end loop;





Example Main, Cont.







	-- Get the ID of a student and display their Geology final examscore

	Integer_IO.Get (ID_Number);

	Student_List.Search (						List => Geology_Class,

							ID => ID_Number,

							Position => Location,

							Found => Student_In_List);

	if Student_In_List then

		Student_List.Retrieve (							List => Geology_Class,

									Position => Location,

									Item => Student_Info);

		Integer_IO.Put (Item => Student_Info.Final_Exam,  Width => 4);

	else

		Text_IO.Put ("Student is not in the Geology class.");

	end if;



end Example;





Enforcing Data Abstraction



	Most of the subprograms for the student list package are relatively small.

Question:	Why not perform the operations directly in the main?



Answer:	Because then the main would become dependent on the implementation details of the list.



Objection:	So what?





Enforcing Data Abstraction, Cont.



	Suppose the following loop:

	-- Print the ID numbers and last names of the students in the Geology Class

	for Index in 1..Student_List.Length (Geology_Class) loop

		Student_List.Retrieve (							List => Geology_Class,

									Position => Index,

									Item => Student_Info);

		Integer_IO.Put (Item => Student_Info.Student_ID, Width => 5);

		Text_IO.Put_Line ("   " & Student_Info.Last_Name);

	end loop;





	Had been implemented as follows:

	-- Print the ID numbers and last names of the students in the Geology Class

	for Index in 1..Student_List.Length (Geology_Class) loop

		Integer_IO.Put (Item => Geology_Class.Items(Index).Student_ID, Width => 5);

		Text_IO.Put_Line ("   " & Geology_Class.Items(Index).Last_Name);

	end loop;





	Consider changing the list so that it is stored in a file, or even just changing the name of the Items field.

-For the first version of the loop, only the student list package would need to be changed.

-In the second version of the loop, both the student list package and the main would need to be changed.





Enforcing Data Abstraction, Cont.







	Good programming dictates that the subprograms defined by the package be used whenever possible, and imple-
mentation details not be accessed directly.

	In its current form, nothing in the program forces the programmer to abide by good programming practices, and 
violations are very typical in such a program.



Enforcing Data Abstraction, Cont.





	For example, the following program both compiles and executes correctly, dispite the lack of appropriate use of 
procedure calls:

	Input_Loop:

	loop

		Text_IO.Get (Class_Code);

		Student_IO.Get (Student_Info);

		if Class_Code = `B' then

			Student_List.Add (Item => Student_Info, List => Biology_Class);

		elsif Class_Code = `G' then

			Geology_Class.Length := Geology_Class.Length + 1;

			Geology_Class.Items(Geology_Class.Length) := Student_Info;

		end if;

	end loop Input_Loop;





	for Index in 1..Student_List.Length (Geology_Class) loop

		Student_List.Retrieve (							List => Geology_Class,

									Position => Index,

									Item => Student_Info);

		Integer_IO.Put (Item => Student_Info.Student_ID, Width => 5);

		Text_IO.Put_Line ("   " & Geology_Class.Items(Index).Last_Name);

	end loop;



Private Types



	Throughout the following, it will be helpful to think of the package developer and the main developer as two dif-
ferent people, where the first is trying to protect the second from bad programming practices.

	In order to enforce data abstraction, Ada provides private types.

	Recall the student list package:

with Student_Types;

package Student_List is



	Max_Length: constant := 100;



	subtype Item_Type is Student_Types.Student_Rec;

	type Item_Array is array (Integer range <>) of Item_Type;

	subtype Index_Type is Integer range 1..Max_Length;

	subtype Length_Type is Integer range 0..Max_Length;

	subtype List_Array is Item_Array(Index_Type);



	type List_Type is

		record

			Length : Length_Type := 0;

			Items : List_Array;

		end record;



	procedure Clear_List (List : in out List_Type);

			:



end Student_List;



Private Types, Cont.



	The package specification could be modified to use a private type as follows (note that the body does not 
change):

with Student_Types;

package Student_List is



	subtype Item_Type is Student_Types.Student_Rec;



	type List_Type is private;



	procedure Clear_List (List : in out List_Type);

			:

private



	Max_Length: constant := 100;



	type Item_Array is array (Integer range <>) of Item_Type;

	subtype Index_Type is Integer range 1..Max_Length;

	subtype Length_Type is Integer range 0..Max_Length;

	subtype List_Array is Item_Array(Index_Type);



	type List_Type is

		record

			Length : Length_Type := 0;

			Items : List_Array;

		end record;



end Student_List;





Private Types, Cont.



	The following main would compile:

	loop

		Text_IO.Get (Class_Code);

		Student_IO.Get (Student_Info);

		if Class_Code = `B' then

			Student_List.Add (Item => Student_Info, List => Biology_Class);

		elsif Class_Code = `G' then

			Student_List.Add (Item => Student_Info, List => Geology_Class);

		end if;

	end loop;



	for Index in 1..Student_List.Length (Geology_Class) loop

		Student_List.Retrieve (List => Geology_Class, Position => Index, Item => Student_Info);

		Integer_IO.Put (Item => Student_Info.Student_ID, Width => 5);

		Text_IO.Put_Line ("   " & Student_Info.Last_Name);

	end loop;



	Integer_IO.Get (ID_Number);

	Student_List.Search (List => Geology_Class, ID => ID_Number, Position => Location, Found => Student_In_List);

	if Student_In_List then

		Student_List.Retrieve (List => Geology_Class, Position => Location, Item => Student_Info);

		Integer_IO.Put (Item => Student_Info.Final_Exam,  Width => 4);

	else

		Text_IO.Put ("Student is not in the Geology class.");

	end if;





Private Types, Cont.



	However, the following main would not compile:

	loop

		Text_IO.Get (Class_Code);

		Student_IO.Get (Student_Info);

		if Class_Code = `B' then

			Student_List.Add (Item => Student_Info, List => Biology_Class);

		elsif Class_Code = `G' then

			Geology_Class.Length := Geology_Class.Length + 1;

			Geology_Class.Items(Geology_Class.Length) := Student_Info;

		end if;

	end loop Input_Loop;



	for Index in 1..Student_List.Length (Geology_Class) loop

		Student_List.Retrieve (List => Geology_Class, Position => Index, Item => Student_Info);

		Integer_IO.Put (Item => Student_Info.Student_ID, Width => 5);

		Text_IO.Put_Line ("   " & Geology_Class.Items(Index).Last_Name);

	end loop;



	Integer_IO.Get (ID_Number);

	Student_List.Search (List => Geology_Class, ID => ID_Number, Position => Location, Found => Student_In_List);

	if Student_In_List then

		Student_List.Retrieve (List => Geology_Class, Position => Location, Item => Student_Info);

		Integer_IO.Put (Item => Student_Info.Final_Exam,  Width => 4);

	else

		Text_IO.Put ("Student is not in the Geology class.");

	end if;



Operations on Private Types



	Recall the student list package:

with Student_Types;

package Student_List is



	subtype Item_Type is Student_Types.Student_Rec;



	type List_Type is private;



	procedure Clear_List (List : in out List_Type);

			:

private



	Max_Length: constant := 100;



	type Item_Array is array (Integer range <>) of Item_Type;

	subtype Index_Type is Integer range 1..Max_Length;

	subtype Length_Type is Integer range 0..Max_Length;

	subtype List_Array is Item_Array(Index_Type);



	type List_Type is

		record

			Length : Length_Type := 0;

			Items : List_Array;

		end record;



end Student_List;







Operations on Private Types, Cont.





	What kinds of things can be done to a variable (of a private type) in a main program?

with Student_List;

procedure Example is



	Biology_Class					: Student_List.List_Type;																		-- Variables of the type can be declared.

	Geology_Class					: Student_List.List_Type;

	Another_Class					: Student_List.List_Type;



begin  -- Example



	Input_Loop:

	loop

			:

		Student_List.Add (Item => Student_Info, List => Biology_Class);																						-- Subprograms can be called.

			:

	end loop Input_Loop;



	Another_Class := Biology_Class;																							-- Assignment.



	if (Geology_Class = Another_Class) then																							-- Comparison for equality and inequality.

		:

	else

		:

	end if;

		:

end Example;





Operations for Private Types, Cont.





Suppose that a package specification contains a private type declaration.  Then another program unit (main, subpro-
gram, or package) that imports this package specification can:



	Declare variables of the private type.

	Call subprograms in the package that have formal parameters of the private type.

	Assign one variable of the private type to another.

	Compare two variables of the private type for equality or inequality.



*Note that accessing implementation details of the private type are prohibitted.





Visibility of Private Information



	In general, if something is declared in a package specification, then it is visible to a client, and throughout the 
specification and body of the package (from the point of declaration).

	In general, if something is declared in a package body, then it is not visible to a client, it is not visible in the spec-
ification, but is visible throughout the body (from the point of declaration).

package Example is															with Example;

															use Example;

	X : Integer;														procedure Main is

	Z : Integer : = Y;						-- Illegal								begin

																X := X + 1;					-- Legal

end Example;																Y := Y + 1;					-- Illegal

															end Main;



package body Example is															*Note that X, Y, and Z could be variable, type, subtype, or subprogram

															  declarations.

	Y : Integer;



	procedure Test is

	begin

		X := X + 1;					-- Legal

		Y := Y + 1;					-- Legal

	end Test;



end Example:





Visibility of Private Information, Cont.



	In addition, if something is declared in the private part of a package specification, then that is only visible in the 
private part of the package specification, and in the package body.

package Example is															with Example;

															use Example;

	X : Integer;														procedure Main is

															begin

																X := X + 1;					-- Legal

private																Z := Z + 1;					-- Illegal

	Z : Integer;														end Main;

end Example;





package body Example is															*Note that X, Y, and Z could be variable, type, subtype, or subprogram

															  declarations.

	Y : Integer;



	procedure Test is

	begin

		X := X + 1;					-- Legal

		Y := Y + 1;					-- Legal

		Z := Z + 1;					-- Legal

	end Test;



end Example:





Equality, Inequality, and Assignment

for Private Types





	Question: What does a test for equality or inequality on two variables of type Class_List do?

	Answer: It compares both fields, Length and Items, in their entirety.

	Note that the Items field is likely to contain garbage in positions Length+1 through Max_Length.

	Thus, two Class_List type variables could be logically "equivalent" yet technically inequal.

	Conclusion: A test for equality (=) or inequality (<>) does not make sense for Class_List type variables.

	Similarly, for other kinds of type declarations, the assignment (:=) operator does not make sense either.



Limited Private Types



	In order to prevent a package user from performing =, <>, and := operations, Ada provides the limited private 
type.

with Student_Types;

package Student_List is



	subtype Item_Type is Student_Types.Student_Rec;



	type List_Type is limited private;																-- Note that this is the only change (including the package body)



	procedure Clear_List (List : in out List_Type);

			:

private



	Max_Length: constant := 100;



	type Item_Array is array (Integer range <>) of Item_Type;

	subtype Index_Type is Integer range 1..Max_Length;

	subtype Length_Type is Integer range 0..Max_Length;

	subtype List_Array is Item_Array(Index_Type);



	type List_Type is

		record

			Length : Length_Type := 0;

			Items : List_Array;

		end record;



end Student_List;





Operations for Limited Private Types





Suppose that a package specification contains a limited private type declaration.  Then another program unit (main, 
subprogram, or package) that imports this package specification can:



	Declare variables of the private type.

	Call subprograms in the package that have formal parameters of the private type.



*Note that accessing implementation details of the private type are prohibitted.  Also note that assignment and com-
parison for equality or inequality are prohibitted as well.





Example Main





	Note that the following main would still compile

with Integer_IO;							-- Preinstantiated I/O package

with Student_Types;

with Student_IO;

with Student_List;

with Text_IO;



procedure Example is

	ID_Number 					: Student_Types.ID_Type;								-- The ID number of a student

	Student_Info					: Student_List.Item_Type;								-- Information for one student

	Student_In_List					: Boolean;								-- Flag for list searchs

	Location					: Student_List.Index_Type;								-- Position of a student in a list



	Class_Code					: Character;   



	-- List variables for the classes

	Biology_Class					: Student_List.List_Type;

	Geology_Class					: Student_List.List_Type;





Example Main, Cont.



begin  -- Example



	-- Get student information for each student and add to proper list

	-- It is assumed that no class has more students than can be stored on a class list

	Input_Loop:

	loop

			:

		Text_IO.Get (Class_Code);

		Student_IO.Get (Student_Info);

		if Class_Code = `B' then

			Student_List.Add (Item => Student_Info, List => Biology_Class);

		elsif Class_Code = `G' then

			Student_List.Add (Item => Student_Info, List => Geology_Class);

		end if;

			:

	end loop Input_Loop;



	-- Print the ID numbers and last names of the students in the Geology Class

	for Index in 1..Student_List.Length (Geology_Class) loop

		Student_List.Retrieve (							List => Geology_Class,

									Position => Index,

									Item => Student_Info);

		Integer_IO.Put (Item => Student_Info.Student_ID, Width => 5);

		Text_IO.Put_Line ("   " & Student_Info.Last_Name);

	end loop;





Example Main, Cont.







	-- Get the ID of a student and display their Geology final examscore

	Integer_IO.Get (ID_Number);

	Student_List.Search (						List => Geology_Class,

							ID => ID_Number,

							Position => Location,

							Found => Student_In_List);

	if Student_In_List then

		Student_List.Retrieve (							List => Geology_Class,

									Position => Location,

									Item => Student_Info);

		Integer_IO.Put (Item => Student_Info.Final_Exam,  Width => 4);

	else

		Text_IO.Put ("Student is not in the Geology class.");

	end if;



end Example;





Another Example Main





	However, the following main would not compile (recall that it did for a private type).

with Student_List;

procedure Example is



	Biology_Class					: Student_List.List_Type;																		-- Variables of the type can be declared.

	Geology_Class					: Student_List.List_Type;

	Another_Class					: Student_List.List_Type;



begin  -- Example



	Input_Loop:

	loop

			:

		Student_List.Add (Item => Student_Info, List => Biology_Class);																						-- Subprograms can be called.

			:

	end loop Input_Loop;



	Another_Class := Biology_Class;																							-- Would not compile!!!



	if (Geology_Class = Another_Class) then																							-- Would not compile!!!

		:

	else

		:

	end if;

		:

end Example;



Equality and Assignment for Limited Private Types



	For a limited private type, assignment and comparison for equality and inequality are provided by programmer 
defined functions.

with Student_Types;

package Student_List is



	subtype Item_Type is Student_Types.Student_Rec;



	type List_Type is limited private;



	procedure Copy(Old_List : in List_Type; New_List : out List_Type);																						-- The "assignment" operator

	function "="(Left : in List_Type; Right : in List_Type) return Boolean;																						-- The equality operation

	procedure Clear_List (List : in out List_Type);

			:

private



	type Item_Array is array (Integer range <>) of Item_Type;

	subtype Index_Type is Integer range 1..100;

	subtype Length_Type is Integer range 0..100;

	subtype List_Array is Item_Array(Index_Type);



	type List_Type is

		record

			Length : Length_Type := 0;

			Items : List_Array;

		end record;



end Student_List;





Implementation of Equality and Assignment

for Limited Private Types



package body Student_List is



	procedure Copy(Old_List : in List_Type; New_List : out List_Type) is

	begin

		New_List := Old_List;

	end Copy;



	function "="(Left : in List_Type; Right : in List_Type) return Boolean is

	begin

		if (Left.Length /= Right.Length) then

			return False;

		end if;



		for I in 1..Left.Length loop

			if (Left.Items(I) /= Right.Items(I)) then

				return False;

			end if;

		end loop;



		return True;

	end "=";



		:



end Student_List;



Example Main



	The following main would now compile.

with Student_List;

use Student_List;																						-- Note that this is required to make = visible

procedure Example is



	Biology_Class					: Student_List.List_Type;																-- Variables of the type can be declared.

	Geology_Class					: Student_List.List_Type;

	Another_Class					: Student_List.List_Type;



begin  -- Example



	Input_Loop:

	loop

			:

		Student_List.Add (Item => Student_Info, List => Biology_Class);																				-- Subprograms can be called.

			:

	end loop Input_Loop;



	Copy(Biology_Class, Another_Class);																					-- Compiles!!!



	if (Geology_Class = Another_Class) then																					-- Compiles!!!

		:

	end if;



	if (Geology_Class /= Another_Class) then																					-- Note that inequality is automatically defined!!!

		:

	end if;

end Example;





Object Packages





	Another way to hide implementation details is to eliminate the private type declaration, and declare a single list 
inside the package body.



with Student_Types;

package Geology_List is																	-- Note the name change!!!



	subtype Item_Type is Student_Types.Student_Rec;



	procedure Clear_List;

	procedure Add(Item : in Item_Type);

	function Length return Length_Type;

	function Full return Boolean;

	procedure Retrieve (Position :  in Index_Type; Item : out Item_Type);

	procedure Search (ID : in Student_Types.ID_Type; Position : out Index_Type; Found : out Boolean);



end Geology_List;





	Note that all types pertaining to the List_Type have been removed, as have all parameters of type List_Type.





Object Packages, Cont.





package body Geology_List is



	Max_Length: constant := 100;



	type Item_Array is array (Integer range <>) of Item_Type;

	subtype Index_Type is Integer range 1..Max_Length;

	subtype Length_Type is Integer range 0..Max_Length;

	subtype List_Array is Item_Array(Index_Type);



	type List_Type is

		record

			Length : Length_Type := 0;

			Items : List_Array;

		end record;



	List : List_Type;																			-- Note this declaration!!!!



	procedure Clear_List is

	begin

		List.Length := 0;

	end Clear_List;

	

	procedure Add(Item : in Item_Type) is

	begin

		List.Length := List.Length + 1;

		List.Items(List.Length) := Item;

	end Add;





Object Packages, Cont.





	function Length return Length_Type is

	begin

		return List.Length;

	end Length;





	function Full return Boolean is

	begin

		return (List.Length = Max_Length);

	end Full;



	procedure Retrieve (Position :  in Index_Type; Item : out Item_Type) is

	begin

		Item := List.Items(Position);

	end Retrieve;



	procedure Search (ID : in Student_Types.ID_Type; Position : out Index_Type; Found : out Boolean) is

	begin

		:

	end Search;



end Student_List;





	Note that each of the subprograms operates on the local variable List, rather than on a parameter.





Object Packages, Cont.





	Now consider a main that uses this package:

with Integer_IO;

with Student_Types;

with Student_IO;

with Geology_List;								-- Imports Geology_List instead of Student_List.

with Text_IO;



procedure Example is

	ID_Number 					: Student_Types.ID_Type;								-- The ID number of a student

	Student_Info					: Geology_List.Item_Type;								-- Information for one student

	Student_In_List					: Boolean;								-- Flag for list searchs

	Location					: Geology_List.Index_Type;								-- Position of a student in a list



	-- Note that Geology_Class does not need to be declared since it is in the Geology_List package.



	-- Note that Class_Code is no longer used since there is only one list.



	-- Similarly note that there is no Biology_Class since there is only one list in this example.





Example Main, Cont.



begin  -- Example



	-- Get student information for each student and add to the list

	-- It is assumed that the class does not have more students than can be stored on a class list

	Input_Loop:

	loop

			:

		Student_IO.Get (Student_Info);																-- Note that the "if" statement is gone.

		Student_List.Add (Item => Student_Info);																-- Note that the list is not an actual parameter.

			:

	end loop Input_Loop;



	-- Print the ID numbers and last names of the students in the Geology Class

	for Index in 1..Student_List.Length loop

		Student_List.Retrieve (							Position => Index,									-- As above, note that the list is not an actual parameter.

									Item => Student_Info);

		Integer_IO.Put (Item => Student_Info.Student_ID, Width => 5);

		Text_IO.Put_Line ("   " & Student_Info.Last_Name);

	end loop;





Example Main, Cont.







	-- Get the ID of a student and display their Geology final exam score

	Integer_IO.Get (ID_Number);

	Student_List.Search (						ID => ID_Number,

							Position => Location,

							Found => Student_In_List);

	if Student_In_List then

		Student_List.Retrieve (							Position => Location,

									Item => Student_Info);

		Integer_IO.Put (Item => Student_Info.Final_Exam,  Width => 4);

	else

		Text_IO.Put ("Student is not in the Geology class.");

	end if;



end Example;





Private Type, Limited Private Type,

and Object Package Summary





	Use a private or limited private type in a package, in order to hide implementation details from the user of that 
package.

-	Prevents the user from accessing data structure details.

-	Forces the user to call subprograms when they want to operate on the variable.



	Use a private or limited private type in a package if the user needs to declare more than one variable of the type.

	Use an object package if the user only needs to declare one variable of the type.

	Use a private type if the default =, /=, and assignment operators make sense for the data type.

	Use a limited private type if any of the default =, /=, and assignment operators don't make sense for the data type.

	Define = and := (copy) subprograms for a limited private type, if necessary.
