Guía mínima de Ada 95

Unidades genéricas en Ada.

    Ada permite crear unidades genéricas, es decir, con parámetros que se pueden concretar para diferentes instancias de la unidad. Para ello basta anteceder la unidad correspondiente con la palabra "generic"; los parámetros formales de la unidad se sitúan en la zona comprendida entre la palabra "generic" y el comienzo de la unidad propiamente dicha. Vemos un ejemplo para el caso de un procedimiento genérico:
    ...
    generic
        type TElemento is private;
    procedure Algo(Elemento:in TElemento) is
        --Declaraciones
    begin
        --Acciones
    end Algo;

    Para utilizar el procedimiento "Algo" primero se deberán crear instancias para los tipos apropiados:
    ...
    procedure Algo_entero is new Algo(TElemento=>integer);
    procedure Algo_carácter is new Algo(character);

    Ahora, ya se pueden invocar los procedimientos "Algo_entero" y "Algo_carácter", según convenga:
    Algo_entero(30);
    Algo_carácter('a');
 

Paquetes genéricos

    Los paquetes genéricos en Ada son los que soportan la genericidad de los tipos abstractos de datos (tad) en este lenguaje. El formato general de un paquete genérico es, en la especificación del paquete:
    generic
        --Zona de declaración de parámetros formales
    package nombre_del_paquete_genérico is
        --Zona de uso de los parámetros formales
    end nombre_del_paquete_genérico;

    En la implementación del paquete:
    package body nombre_del_paquete_genérico is
        --Zona de uso de los parámetros formales
    end nombre_del_paquete_genérico;

    Los parámetros formales se pueden emplear en la implementación del paquete (package body) sin más requerimientos.

    La forma de usar un paquete genérico es crear una instancia del paquete genérico en la que se especifiquen todos los parámetros formales requeridos. Esta sentencia tiene la forma:
    package nombre_instancia is new nombre_del_paquete_genérico(parámetros_actuales,...);

Parámetros formales

  Los parámetros formales pueden ser: objetos, tipos o subprogramas. Al igual que los parámetros de los subprogramas, los parámetros de un paquete genérico pueden tener un valor por defecto. Los parámetros formales se declaran de distinta forma según su naturaleza:

Ejemplo:

    El siguiente código muestra la declaración, implementación y uso de un paquete genérico para manejar listas ordenadas.
Fichero de especificación (*.ads)
-- Se declara un paquete genérico para manejar listas ordenadas
-- Se pasan como parámetros:
--    El Tamaño máximo de la Lista (por defecto 10)
--    El tipo de dato que se va a almacenar en la Lista
--    Una operación de comparación
--    Una acción aplicable a un elemento de la Lista

  generic
      Tamaño : Natural := 10; -- Tamaño por defecto
      type Telemento is private; -- Tipo de dato a almacenar.
        -- El paquete no necesita conocer de Telemento mas que
        -- las operaciones que vienen a continuación
      with function "<"(X,Y: in Telemento) return Boolean is <>;
        -- Operación de comparación de elementos
      with procedure Accion(X: in Telemento);
        -- Operación que se aplica a un elemento

  package Lista_Ordenada is
      type Tlista is private; -- La implementación de la lista queda oculta
      procedure Insertar(X: in Telemento; L: in out Tlista);
        -- Inserta un elemento en la lista
      procedure Extraer(I: in Natural; L: in out Tlista);
        -- Extrae un elemento de la lista
      procedure Iterar(L: in Tlista);
        -- Recorre la lista aplicando una operación a cada elemento

  private  -- Estructura de datos de la lista
      type Contenedor is array (1..Tamaño) of Telemento;
      type Tlista is record
         Elementos : Contenedor;
         Num_Elementos : Natural := 0;
      end record;
  end Lista_Ordenada;

Fichero de implementación (*.adb)
-- Implementación de las operaciones de la lista ordenada

package body Lista_Ordenada is

  procedure Insertar(X: in Telemento; L: in out Tlista) is
      I : Natural;
  begin
      I := 1;
      -- Esquema de búsqueda para la localización de la posición
      while I <= L.Num_Elementos and then L.Elementos(I) < X loop
          I := I + 1;
      end loop;
      L.Num_Elementos := L.Num_Elementos + 1;--Posible Constrain Error
      if I < L.Num_Elementos then
          -- Se desplazan los elementos para insertar el nuevo
          for J in reverse I+1..L.Num_Elementos loop
              L.Elementos(J) := L.Elementos(J-1);
          end loop;
      end if;
      L.Elementos(I) := X;
  end Insertar;

  procedure Extraer(I: in Natural; L: in out Tlista) is
  begin
      -- Se desplazan los elementos para cubrir el hueco de la extracción
      for J in I..L.Num_Elementos-1 loop
          L.Elementos(J) := L.Elementos(J+1);
      end loop;
      L.Num_Elementos := L.Num_Elementos - 1;--Posible Constrain Error
  end Extraer;

  procedure Iterar(L: in Tlista) is
  begin
      -- Esquema de recorrido sobre la lista
      for J in 1..L.Num_Elementos loop
         Accion(L.Elementos(J));-- Se aplica la acción pasada como parámetro
      end loop;
  end Iterar;

 end Lista_Ordenada;

Fichero del programa principal (*.ada)
with Text_Io,Lista_Ordenada;
use Text_Io;

procedure Prueba_De_Contenedor is
    package Enteros_Io is new Integer_Io(Integer);
    use Enteros_Io;

    procedure Escribir_Elemento(X: in Integer) is
    begin
       Put(X);
       New_Line;
    end;
    -- Se crea una instancia del paquete genérico Lista_Ordenada, llamada
    -- Lista_Enteros, con un tamaño máximo de 20, los elementos que se almacenan
    -- son de tipo integer, la operación de comparación es el operador "<" de
    -- los integer (al no especificarlo se usa por defecto), como accion se pasa
    -- el procedimiento Escribir_Elemento
    package Lista_Enteros is new Lista_Ordenada(20,Integer,Accion => Escribir_Elemento);
    use Lista_Enteros ;

    L: Tlista;
begin
    for J in reverse 1..15 loop
        Insertar(J,L);
    end loop;
    Iterar(L);
end Prueba_De_Contenedor;



[Anterior][Inicio][Siguiente]