Ada: Understanding private types and understanding packaging

ada, package, private

Solution

why do not I have to use the methods set_Horz(A) and set_Vert(A) prior to issuing the command

Because you're setting the fields of your private record by executing:

Rectangular_Form.Vector_Basis_r (A => Theta, D => Basis_r);

(Review the implementation of Vector_Basis_r.)

-- EXPANDED Answer

When you declare the Basis_r variable in your Test_Rectangular_Form procedure, the memory for that "Rectangular" variable is allocated. At this point the Horz and Vert fields in the private type are present, but unset (they could contain anything).

When you call Rectangular_Form.Vector_Basis_r, its implementation sets the values of those private fields. Maybe this is what's confusing you: the body of the package in which a private type is declared has direct access to those fields. This is exactly the aspect that Vector_Basis_r is exploiting when setting their values (as well as Set_Vert and Set_Horz).

Problem

I am trying to learn how to use private declarations in Ada and also to understand packaging. I have tried to keep my codes as short as possible. We start with the main file `rectangular_Form.ads` ``` with Rectangular_Method_1; package Rectangular_Form renames Rectangular_Method_1; -- with Rectangular_Method_2; -- package Rectangular_Form renames Rectangular_Method_2; ``` This tells us that we can have two implementations and that for now `Rectangular_Method_1` has been chosen. Then we have the specifications file `Rectangular_Method_1.ads`: ``` package Rectangular_Method_1 is type Rectangular is private; procedure Vector_Basis_r (A : in Long_Float; D : out Rectangular); procedure Set_Horz (R : in out Rectangular; H : Long_Float); function Get_Horz (R : Rectangular) return Long_Float; private type Rectangular is record Horz, Vert: Long_Float; end record; end Rectangular_Method_1; ``` and its body `Rectangular_Method_1.adb`: ``` with Ada.Numerics.Long_Elementary_Functions; use Ada.Numerics.Long_Elementary_Functions; package body Rectangular_Method_1 is procedure Vector_Basis_r (A : in Long_Float; D : out Rectangular) is begin D.Horz := Cos (A, Cycle => 360.0); D.Vert := Sin (A, Cycle => 360.0); end Vector_Basis_r; procedure Set_Horz (R : in out Rectangular; H : Long_Float) is begin R.Horz := H; end Set_Horz; function Get_Horz (R : Rectangular) return Long_Float is begin return R.Horz; end Get_Horz; end Rectangular_Method_1; ``` and finally the test script: `test_rectangular_form.adb`: ``` with Ada.Long_Float_Text_IO; with Ada.Text_IO; use Ada.Text_IO; with Rectangular_Form; use type Rectangular_Form.Rectangular; procedure Test_Rectangular_Form is Component_Horz, Component_Vert, Theta : Long_Float; Basis_r : Rectangular_Form.Rectangular; begin Ada.Text_IO.Put("Enter the angle "); Ada.Long_Float_Text_IO.Get (Item => theta); --Vector basis Rectangular_Form.Vector_Basis_r (A => Theta, D => Basis_r); Ada.Text_IO.New_Line; Ada.Text_IO.Put("rhat_min_theta = "); Ada.Long_Float_Text_IO.Put (Item => Rectangular_Form.Get_Horz (Basis_r), Fore => 3, Aft => 5, Exp => 0); Ada.Text_IO.Put(" ihat + "); Ada.Long_Float_Text_IO.Put (Item => Rectangular_Form.Get_Vert (Basis_r), Fore => 3, Aft => 5, Exp => 0); Ada.Text_IO.Put (" jhat "); end Test_Rectangular_Form; ``` Question (applied to `test_rectangular_form.adb`): I am getting the components `A.Horz` and `A.Vert` directly using ``` Rectangular_Form.Vector_Basis_r (A => Theta, D => Basis_r); ``` and accessing the horizontal and vertical components later on by just using ``` Rectangular_Form.Get_Horz (Basis_r) ``` and ``` Rectangular_Form.Get_Vert (Basis_r) ``` This seems OK as I am using the methods `Get_Horz` and `Get_Vert` to access the private Rectangular horizontal and vertical components. However I am reading the variable `Theta` directly from the command line and finding its horizontal and vertical components using ``` Rectangular_Form.Vector_Basis_r (A => Theta, D => Basis_r); ``` If the Rectangular components `A.Horz` and `A.Vert` are private as I have defined them, why do not I have to use the methods `set_Horz(A)` and `set_Vert(A)` prior to issuing the command ``` Rectangular_Form.Vector_Basis_r (A => Theta, D => Basis_r); ``` PS: The functions for `Set_Vert` and `Get_Vert` were omitted to keep the codes short. Thanks a lot...

Original source