A. Classes: Tagged Types - JulTob/Ada GitHub Wiki

To implement a proper class you need to use a package just as a library.

Inside it, you define the objects, the constructors, the methods and functions.

A class is the abstract collection of all these to one specific idea or concept.

A class in C++ or Java corresponds to a tagged type in Ada.

type T is tagged record
   V, W : Integer;
  end record;

type T_Access is access all T;

function F (V: T) return Integer;
procedure P1 (Pnt: access T);
procedure P2 (Pnt: T_Access);
-- Note that P2 is not a primitive of T—it does not have any parameters of type T. 
-- Its parameter is of type T_Access, which is a different type.

Once declared, primitives can be called like any subprogram with every necessary parameter specified, or called using prefix notation. For example:

declare
   V : T;
  begin
   V.P1; -- Wait what?? -- Check later
  end;
type C (discriminant : type) is new parent_class 
   and interface
with record
  --  Declarations
end record; 

Constructors

Constructors are functions that return objects of the class record, instantiated to some values.

function new_Web_Page return Web_Page is
...

Destructors.

Usually automated, processes that deallocate the memory taken by the record object.

Class as Access to structures

Another definition of classes is just accesses to structures. THese can be defined as follows:

declare
   type R is Record
      A, B: Integer
      end record;
   type C is access R;
   Obj1, Obj2: C;
   type A_int is access Integer;
   int: A_int := new Integer;
   begin
     Obj1 := new R;
     Obj1.A := 0;
     Obj2 := Obj1;  
       -- They Point to the same object! -- Java style
     Obj2.A:= 1;
       -- Obj1.A is also 1 now

     -- Content access
     Obj1.all := (1,0);
     Obj2.all := Obj1.all;
     Obj2.A := Obj1.all.A; 
     -- The .all append is optionall if clear it mean 
     int.all := 0;
     -- Specifically refers to cocntent
     -- int := 0 mightn semantically mean "Ground-pointer"
     end;
---Base.ads
package Base is
   type Base_Type is tagged
      record
         B : Integer;
      end record;
   procedure P1(X : Base_Type);
   procedure P2(X : out Base_Type);
   procedure P3(X : Base_Type; Y : Base_Type);
   function F return Base_Type;
end Base;
---Base.adb
with Ada.Text_IO; use Ada.Text_IO;

package body Base is

  procedure P1(X : Base_Type) is begin
      Put_Line("Base.P1"); end P1;

  procedure P2(X : out Base_Type) is begin
      Put_Line("Base.P2");
      X.B := 0;
      end P2;

   procedure P3(X: Base_Type; Y : Base_Type) is begin
      Put_Line("Base.P3");
      end;

   function F return Base_Type is begin
      Put_Line("Base.F");
      return (B => 0);
      end F;
end Base;

--- Derived.ads
with Base;

package Derived is

   type Derived_Type is new Base.Base_Type with
     record
        D : Integer;
     end record;

   overriding procedure P1(X : Derived_Type);
   overriding procedure P2(X : out Derived_Type);
   overriding procedure P3(X : Derived_Type; Y : Derived_Type);
   overriding function F return Derived_Type;
end Derived;

--- Derived.adb
with Ada.Text_IO; use Ada.Text_IO;
with Base;
with Derived;

procedure Tagged_Demo is

   procedure Test(X : Base.Base_Type'Class) is
      Y : Base.Base_Type'Class := X;
   begin
      Base.P1(X);
      Base.P2(Y);
      Y := Base.F;
   end Test;

   procedure Test2 (X, Y : Base.Base_Type'Class) is
   begin
      Base.P3(X, Y);
   end Test2;

   X : constant Base.Base_Type := (B => 10);
   Y : constant Derived.Derived_Type := (B => 10, D => 20);
begin

   Put_Line("Testing regular types.");
   Base.P1(X);
   -- Base.P1(Y);  -- Compile error due to type mismatch.
   -- Derived.P1(X);  -- Compile error due to type mismatch.
   Derived.P1(Y);

   New_Line;
   Put_Line("Testing class-wide types.");
   Test(X);
   Test(Y);
   Test2(X, X);
   -- Test2(X, Y);  -- Raises Constraint_Error at run time.
   -- Test2(Y, X);  -- Raises Constraint_Error at run time.
   Test2(Y, Y);
end Tagged_Demo;

--- tagged_Demo.adb
with Ada.Text_IO; use Ada.Text_IO;
with Base;
with Derived;

procedure Tagged_Demo is

   procedure Test(X : Base.Base_Type'Class) is
      Y : Base.Base_Type'Class := X;
   begin
      Base.P1(X);
      Base.P2(Y);
      Y := Base.F;
   end Test;

   procedure Test2 (X, Y : Base.Base_Type'Class) is
   begin
      Base.P3(X, Y);
   end Test2;

   X : constant Base.Base_Type := (B => 10);
   Y : constant Derived.Derived_Type := (B => 10, D => 20);
begin

   Put_Line("Testing regular types.");
   Base.P1(X);
   -- Base.P1(Y);  -- Compile error due to type mismatch.
   -- Derived.P1(X);  -- Compile error due to type mismatch.
   Derived.P1(Y);

   New_Line;
   Put_Line("Testing class-wide types.");
   Test(X);
   Test(Y);
   Test2(X, X);
   -- Test2(X, Y);  -- Raises Constraint_Error at run time.
   -- Test2(Y, X);  -- Raises Constraint_Error at run time.
   Test2(Y, Y);
end Tagged_Demo;

Example: Robots!

ADS

package Asimov is
  type Robot is tagged private; --declaration of a class
  type Reference is access all Robot'Class -- A classwide access
  procedure On(R: in out Robot);
  procedure Off(R: in out Robot);
  function Is_On(R: in Robot) return Boolean;
private Robot is tagged record -- tagged record = class
  On: Boolean := False;
  end record;;
end Asimov;

ADB

with Ada.Text_IO; use Ada;
package body Asimov is

  function Is_On (R: Robot) return Boolean is
    BEGIN RETURN R.IS_ON; end IS_ON;

  procedure ON(R: in out Robot) is 
    begin
    R.ON := True;
    end ON;

  procedure OFF(R: in out Robot) is 
    begin
    R.ON := False;
    end OFF;
  

Un tipo tagged es un tipo privado o un record en cuya declaración se usa la palabra reservada tagged.

Un tipo tagged puede ser extendido, dando lugar a otro tipo que se dice derivado de aquel. El tipo del que se deriva se dice que es "padre" del derivado. Del tipo derivado se pueden a su vez derivar otros, formando una jerarquía de tipos (una familia de tipos). Los tipos derivados también son tagged. Cada objeto tagged tiene un atributo llamado Tag que identifica su clase concreta.

El tipo primitivo de una jerarquía no tiene por qué tener ningún campo, de forma que sólo existan los añadidos por sus extensiones.

package Ejemplo is
   type Persona is tagged private; --  Declaración de tipo tagged

private
   type Persona is tagged record
      Nombre : String (1 .. 50);
      NIF : String (1 .. 9);
   end record;
end Ejemplo;

Tipo primitivo sin campos:

type Otro is tagged null record;