package <nombre_de_paquete> is
<elementos públicos>
private
<elementos privados>
end <nombre_de_paquete>;
La parte anterior a la palabra "private" constituye la interfaz de los servicios ofertados por el paquete (son accesibles a quien lo use). La parte que sigue constituye la parte privada de la especificación, tales como la estructura de datos con que se implementa un tipo ofrecido en la intefaz u otros elementos similares. La palabra "private" puede omitirse, en cuyo caso se entiende que la parte privada de la especificación es nula. La siguiente especificación es de un paquete llamado "Pila_De_enteros" que ofrece un tipo llamado "Pila" y cuatro operaciones primitivas para manejar pilas de valores de tipo Integer.
package Pila_De_Enteros is
type Pila is limited private;
procedure Apilar(P: in out Pila;E: in
Integer);
procedure Desapilar(P: in out Pila);
function Cima(P: Pila) return Integer;
function Es_Vacía(P:Pila) return Boolean;
private
type Nodo is record
Info: Integer;
Sig : Pila;
end record;
type Pila is access Nodo;
end Pila_De_Enteros;
package body <nombre_de_paquete>
is
<desarrollo del paquete>
end <nombre_de_paquete>;
Todas las declaraciones hechas en la especificación del paquete se pueden usar en la implementación (body), aunque estén en la parte "private". Las declaraciones hechas en el "package body" sólo se pueden usar en el mismo. A continuación se muestra el "package body" del paquete "Pila_de_enteros":
with Unchecked_Deallocation;
package body Pila_De_Enteros is
procedure Libera is new Unchecked_Deallocation(Nodo,Pila);
procedure Apilar(P: in out Pila;E: in
Integer) is
begin
P := new Nodo'(E,P);
end Apilar;
procedure Desapilar(P: in out Pila) is
Aux: Pila := P;
begin
P := P.Sig;
Libera(Aux);
end Desapilar;
function Cima(P: Pila) return Integer is
begin
return P.Info;
end Cima;
function Es_Vacía(P:Pila) return Boolean
is
begin
return P = null;
end Es_Vacía;
end Pila_De_Enteros;
with Text_Io,
Ada.Integer_Text_Io,
Pila_De_Enteros;
use Text_Io,
Ada.Integer_Text_Io,
Pila_De_Enteros;
procedure Prueba is
P: Pila;
begin
for I in 1..5 loop
Apilar(P,I);
end loop;
while not Es_Vacía(P) loop
Put(Cima(P));
New_Line;
Desapilar(P);
end loop;
end Prueba;
Especificación: se añade la lista de parámetros genéricos formales y se sustituyen todas las apariciones de Integer por T_Elemento, el párametro formal del paquete:
generic
type T_Elemento is private;
package Pilas is
type Pila is limited private;
procedure Apilar(P: in out Pila;E: in
T_Elemento);
procedure Desapilar(P: in out Pila);
function Cima(P: Pila) return T_Elemento;
function Es_Vacía(P:Pila) return Boolean;
private
type Nodo is record
Info: T_Elemento;
Sig : Pila;
end record;
type Pila is access Nodo;
end Pilas;
Implementación: se sustituyen todas las apariciones de Integer por T_Elemento:
with Unchecked_Deallocation;
package body Pilas is
procedure Libera is new Unchecked_Deallocation(Nodo,Pila);
procedure Apilar(P: in out Pila;E: in
T_Elemento) is
begin
P := new Nodo'(E,P);
end Apilar;
procedure Desapilar(P: in out Pila) i
s
Aux: Pila := P;
begin
P := P.Sig;
Libera(Aux);
end Desapilar;
function Cima(P: Pila) return T_Elemento
is
begin
return P.Info;
end Cima;
function Es_Vacía(P:Pila) return Boolean
is
begin
return P = null;
end Es_Vacía;
end Pilas;
Utilización: el nuevo paquete, "Pilas", aparece en la sentencia with de la cláusula de contexto, pero no así en la use puesto que al ser genérico es sólo una plantilla a partir de la cual definir instancias, pero no es en sí mismo una unidad utilizable directamente. La definición de una instancia se hace especificando un nombre para el paquete no genérico al que dará lugar y los valores reales correspondientes a los parámetros (al menos de aquellos que no tengan un valor por defecto):
with Text_Io,
Ada.Integer_Text_Io,
Pilas;
use Text_Io,
Ada.Integer_Text_Io;
procedure Prueba is
package Pila_De_Enteros is new Pilas(Integer);
use Pila_De_Enteros;
package Pila_De_Reales is new Pilas(Float);
use Pila_De_Reales;
P: Pila_De_Enteros.Pila;
Q: Pila_De_Reales.Pila;
begin
for I in 1..5 loop
Apilar(P,I);
end loop;
while not Es_Vacía(P) loop
Put(Cima(P));
New_Line;
Desapilar(P);
end loop;
end Prueba;
generic
package Pilas.Copiables is
Vacía: constant Pila;
procedure Copia(Pe: in Pila;Ps: out
Pila);
private
Vacía: constant Pila := null;
end Pilas.Copiables;
Un paquete derivado de otro genérico tiene obligatoriamente que ser genérico (aunque no precise parámetros, los precisa su padre). De un paquete no genérico se puede derivar uno genérico.
package body Pilas.Copiables is
procedure Vaciar(P: in out Pila) is
begin
while not Es_Vacía(P)
loop
Desapilar(P);
end loop;
end Vaciar;
function Copia(P:Pila) return Pila is
begin
if Es_Vacía(P) then
return Vacía;
else
return new
Nodo'(Cima(P),Copia(P.Sig));
end if;
end Copia;
procedure Copia(Pe: in Pila;Ps: out
Pila) is
Aux: Pila := Copia(Pe);
begin
Vaciar(Ps);
Ps := Aux;
end Copia;
end Pilas.Copiables;
Obsérvese que ni en la especificación ni en la implementación aparece el paquete original en una cláusula de contexto; no es necesario dado que es una extensión del paquete y como tal tiene acceso a todo lo declarado en la especificación del original, incluida la parte privada, aunque no así a lo desarrollado en el "package body" .
Una unidad que requiera toda la funcionalidad de los dos paquetes necesitará incluirlos a ambos.
with Text_Io, Ada.Integer_Text_Io, Pilas, Pilas.Copiables;
use Text_Io, Ada.Integer_Text_Io;
procedure Prueba is
package Pila_De_Enteros is new Pilas(Integer);
use Pila_De_Enteros;
package Pilas_C is new Pila_De_Enteros.Copiables;
use Pilas_C;
P,Q: Pila;
begin
for I in 1..5 loop
Apilar(P,I);
end loop;
Copia(P,Q);
Copia(Vacía,P);
while not Es_Vacía(Q) loop
Put(Cima(Q));
New_Line;
Desapilar(Q);
end loop;
end Prueba;
Los paquetes derivados y sus ancestros forman una jerarquía que se conoce como familia o sistema de paquetes.
Grupo de Estructuras de Datos y Lingüística Computacional - ULPGC
Anterior | Superior | Siguiente