# Programación en Ada/Unidades genéricas
## Polimorfismo paramétrico

La idea de reutilización de código surge ante la necesidad de construir programas en base a componentes bien establecidos que pueden ser combinados para formar un sistema más amplio y complejo. La reutilización de componentes mejora la productividad y la calidad del software. El lenguaje Ada soporta esta característica mediante las unidades genéricas.
Una unidad genérica es aquella en la que se manipulan tipos que posteriormente instanciará el usuario, es decir, se utiliza a modo de plantilla. Se pueden hacer unidades genéricas de subprogramas y paquetes. Sintácticamente se podría describir como:
Por ejemplo, para reutilizar un procedimiento de intercambio de variables:
La especificación del subprograma va precedida por la parte formal genérica, que consta de la palabra reservada generic seguida por una lista de parámetros formales genéricos que puede ser vacía.
El subprograma Intercambiar es genérico y se comporta como una plantilla. Hay que destacar que las entidades declaradas como genéricas no son locales, por ello es necesario instanciarlas. Por ello, para poder utilizar la unidad del ejemplo es necesario crear una instancia suya para el tipo que se quiera usar, su sintaxis sería:
Por ejemplo:
Con ello, se puede utilizar el procedimiento para tipos Integer, si se quiere utilizar para cualquier otro tipo basta con volver a instanciarlo para el nuevo tipo con otro nombre o, si se utiliza el mismo identificador en la instanciación, se sobrecarga el procedimiento y puede ser utilizado para distintos tipos:
De igual modo, se pueden emplear paquetes genéricos, por ejemplo, para implementar una plantilla del tipo abstracto de datos pila:
Ahora se podría utilizar una pila de un tamaño y tipo determinados, para ello, habría que crear un ejemplar, por ejemplo, de esta manera:
En la segunda línea del código anterior se ha creado una instancia del paquete Plantilla_pila que se llama Pila_reales_de_100. A partir de ese momento se pueden acceder a los miembros del paquete, ya que la creación de la instancia implica su visibilidad (igual que si se ejecutara la sentencia with Pila_reales_de_100;).

## Parámetros de unidades genéricas

Resaltar que los objetos declarados como parámetros formales son de modo in por defecto y pueden ser in o in out, pero nunca out. En el caso de que sea in, se comportará como una constante cuyo valor lo proporciona el parámetro real correspondiente. Como resulta obvio, un parámetro genérico in no puede ser de un tipo limitado, pues no se permite la asignación y el parámetro formal toma su valor mediante asignación. En el caso de que el parámetro genérico sea de modo in out, se comporta como una variable que renombra al parámetro real correspondiente; en este caso, el parámetro real debe ser el nombre de una variable y su determinación se realiza en el momento de la creación del ejemplar.
Además de parámetros genéricos de tipo y objetos, se pueden incluir parámetros formales de subprogramas o paquetes, por ejemplo:
Se utilizaría, por ejemplo, con matrices (teniendo previamente definida la operación de multiplicación de matrices), de la siguiente manera:
Los tipos formales de un genérico se pueden especificar para que pertenezcan a una determinada clase de tipos.
| Tipo formal | Instanciable con |
| type T is private; | Cualquier tipo con operador de igualdad y asignación definidos |
| type T (D : TD) is limited private; | Cualquier tipo con discriminante de tipo TD |
| type T (<>) is private; | Cualquier tipo con cualquier discriminante |
| type T is limited private; | Cualquier tipo (sea limitado o no) |
| type T is (<>); | Cualquier tipo discreto |
| type T is range <>; | Cualquier tipo entero con signo |
| type T is delta <>; | Cualquier tipo de coma fija |
| type T is digits <>; | Cualquier tipo de coma flotante |
| type T is array (I) of E; | Cualquier tipo array con índice I y tipo de elementos E (I y E podrían ser a su vez otros parámetros formales) |
| type T is access O; | Cualquier tipo puntero que apunte a objetos de tipo O (O podría ser a su vez otro parámetro formal) |
En el cuerpo sólo podemos hacer uso de las propiedades de la clase de tipo del parámetro real. Es decir, a diferencia de las plantillas de C++, la especificación del genérico es un contrato que ha de cumplir la implementación.

## Ver también

* Polimorfismo en Wikipedia
* Generic programming en Wikipedia en inglés

## Manual de referencia de Ada

* Section 12: Generic Units