Privacy
Directions
Goal: create a package that handles directions and geometric angles using a previous implementation.
Steps:
Fix the implementation of the
Test_Directions
procedure.
Requirements:
The implementation of the
Test_Directions
procedure must compile correctly.
Remarks:
This exercise is based on the Directions exercise from the Records labs.
In this version, however,
Ext_Angle
is a private type.In the implementation of the
Test_Directions
procedure below, the Ada developer tried to initializeAll_Directions
— an array ofExt_Angle
type — with aggregates.
Since we now have a private type, the compiler complains about this initialization.
To fix the implementation of the
Test_Directions
procedure, you should use the appropriate function from theDirections
package.The initialization of
All_Directions
in the code below contains a consistency error where the angle doesn't match the assessed direction.
See if you can spot this error!
This kind of errors can happen when record components that have correlated information are initialized individually without consistency checks — using private types helps to avoid the problem by requiring initialization routines that can enforce consistency.
Limited Strings
Goal: work with limited private
types.
Steps:
Implement the
Limited_Strings
package.
Implement the
Copy
function.Implement the
=
operator.
Requirements:
For both
Copy
and=
, the two parameters may refer to strings with different lengths. We'll limit the implementation to just take the minimum length:
In case of copying the string "Hello World" to a string with 5 characters, the copied string is "Hello":
S1 : constant Lim_String := Init ("Hello World"); S2 : Lim_String := Init (5); begin Copy (From => S1, To => S2); Put_Line (S2); -- This displays "Hello".When comparing "Hello World" to "Hello", the
=
operator indicates that these strings are equivalent:S1 : constant Lim_String := Init ("Hello World"); S2 : constant Lim_String := Init ("Hello"); begin if S1 = S2 then -- True => This branch gets selected.When copying from a short string to a longer string, the remaining characters of the longer string must be initialized with underscores (
_
). For example:S1 : constant Lim_String := Init ("Hello"); S2 : Lim_String := Init (10); begin Copy (From => S1, To => S2); Put_Line (S2); -- This displays "Hello_____".
Remarks:
As we've discussed in the course:
Variables of limited types have the following limitations:
they cannot be assigned to;
they don't have an equality operator (
=
).We can, however, define our own, custom subprograms to circumvent these limitations:
In order to copy instances of a limited type, we can define a custom
Copy
procedure.In order to compare instances of a limited type, we can define an
=
operator.You can use the
Min_Last
constant — which is already declared in the implementation of these subprograms — in the code you write.Some details about the
Limited_Strings
package:
The
Lim_String
type acts as a container for strings.
In the the private part,
Lim_String
is declared as an access type to aString
.There are two versions of the
Init
function that initializes an object ofLim_String
type:
The first one takes another string.
The second one receives the number of characters for a string container.
Procedure
Put_Line
displays object ofLim_String
type.The design and implementation of the
Limited_Strings
package is very simplistic.
A good design would have better handling of access types, for example.
Bonus exercise
In previous labs, we had many source-code snippets containing records that
could be declared private. The source-code for the exercise above
(Directions) is an example: we've modified the type declaration of
Ext_Angle
, so that the record is now private. Encapsulating the
record components — by declaring record components in the private
part — makes the code safer. Also, because many of the code snippets
weren't making use of record components directly (but handling record
types via the API instead), they continue to work fine after these
modifications.
This exercise doesn't contain any source-code. In fact, the goal here is to modify previous labs, so that the record declarations are made private. You can look into those labs, modify the type declarations, and recompile the code. The corresponding test-cases must still pass.
If no other changes are needed apart from changes in the declaration, then that indicates we have used good programming techniques in the original code. On the other hand, if further changes are needed, then you should investigate why this is the case.
Also note that, in some cases, you can move support types into the private
part of the specification without affecting its compilation. This is the case,
for example, for the People_Array
type of the List of Names lab
mentioned below. You should, in fact, keep only relevant types and subprograms
in the public part and move all support declarations to the private part of the
specification whenever possible.
Below, you find the selected labs that you can work on, including changes that you should make. In case you don't have a working version of the source-code of previous labs, you can look into the corresponding solutions.
Colors
Chapter: Records
Steps:
Change declaration of
RGB
type toprivate
.
Requirements:
Implementation must compile correctly and test cases must pass.
List of Names
Chapter: Arrays
Steps:
Change declaration of
Person
andPeople
types tolimited private
.Move type declaration of
People_Array
to private part.
Requirements:
Implementation must compile correctly and test cases must pass.
Price List
Chapter: More About Types
Steps:
Change declaration of
Price_List
type tolimited private
.
Requirements:
Implementation must compile correctly and test cases must pass.