Logo

Marco Cantù
Pascal Esencial

Capítulo 11 Actualizar
Programas y unidades

Las aplicaciones escritas en Delphi hacen un uso intensivo de unidades, o módulos de programa. De hecho, las unidades fueron la base de la modularidad del lenguaje antes de que se introdujeran las clases. En una aplicación Delphi, cada formulario viene respaldado por su unidad correspondiente. Cuando se añade un nuevo formulario a un proyecto (con el botón de herramienta correspondiente o el comando de menú Archivo > Nuevo formulario...), en realidad, Delphi añade una nueva unidad, que define la clase para el nuevo formulario.

Unidades

Aunque cada formulario se define mediante una unidad, el recíproco no es cierto. Las unidades no tienen por qué definir formularios. Pueden, simplemente, definir y hacer disponible una colección de rutinas. Seleccionando el comando Archivo > Nuevo y luego el icono Unit en la página New del Object Repository, se añade una unidad en blanco al proyecto actual. Esta unidad en blanco contiene el siguiente código, delimitando las secciones en que se divide una unidad :

unit Unit1;

interface

implementation

end.

El concepto de unidad es sencillo. Una unidad tiene un único nombre, que corresponde a su nombre de archivo, una sección de interfaz que declara qué es visible a otras unidades, y una sección de implementación con el código auténtico y otras declaraciones ocultas. Finalmente, la unidad puede tener una sección de inicialización opcional con cierta porción de código de inicio, que se ejecuta cuando el programa se carga en la memoria; también puede tener una sección de finalización, opcional, que se ejecutaría al terminar el programa.

La estructura general de una unidad, con todas sus secciones posibles, es la siguiente:

unit unitName;

interface

// otras unidades a que necesitamos referirnos
uses
  A, B, C;

// definición del tipo exportado
type
  newType = TypeDefinition;

// constantes exportadas
const
  Zero = 0;

// variables globales
var
  Total: Integer;

// lista de funciones y procedimientos exportados
procedure MyProc;

implementation

uses
  D, E;

// variable global oculta
var
  PartialTotal: Integer;

// todas las funciones exportadas deben ser codificadas
procedure MyProc;
begin
  // ... código del procedimiento MyProc
end;

initialization
  // parte de inicialización, opcional

finalization
  // código de limpieza, opcional

end.

La cláusula uses, al principio de la sección de interfaz, indica a qué otras unidades tenemos que acceder en la porción de interfaz de la unidad. Esto incluye las unidades que definen los tipos de datos a que nos referimos en la definición de otros tipos de datos, como las componentes dentro de un formulario que estemos definiendo.

La segunda cláusula uses, al principio de la sección de implementación, indica otras unidades, a que necesitamos acceder sólo en el código de implementación. Cuando necesite referirse a otras unidades del código de las rutinas y métodos, deberá añadir elementos en esta segunda cláusula uses, en vez de hacerlo en la primera. Todas las unidades a que se refiera deben estar presentes en el directorio del proyecto o un directorio de la ruta de búsqueda (puede establecer la ruta de búsqueda de un proyecto en la página Directories/Conditionals del cuadro de diálogo Options del proyecto).

Los programadores en C++ deberán tener en cuenta que la instrucción uses no se corresponde con una directiva include. El efecto de una instrucción uses es importar sólo la porción de interfaz precompilada de las unidades listadas. La porción de implementación de la unidad se considera sólo cuando tal unidad se compila. Las unidades a que se refiera pueden estar tanto en formato de código fuente (PAS) o formato compilado (DCU), pero la compilación tiene que haber tenido lugar en la misma versión de Delphi.

El interfaz de una unidad puede declarar bastantes elementos diferentes, incluyendo procedimientos, funciones, variables globales y tipos de datos. En las aplicaciones Delphi, los tipos de datos son los que, probablemente, se utilicen más a menudo. Delphi automáticamente sitúa un tipode datos de clase nueva en una unidad cada vez que usted cree un formulario. De cualquier modo, contener definiciones de formulario no es la única finalidad de las unidades en Delphi.

Puede seguir utilizando unidades convencionales, con funciones y procedimientos, y puede hacer uso de unidades con clases que no se refieran a formularios u otros elementos visuales.

Unidades y accesibilidad

En Pascal, las unidades son la clave para el encapsulamiento y la accesibilidad, y son, probablemente, aún más importantes que las palabras claves privadas y públicas de una clase. (De hecho, como veremos en el capítulo 12 <en preparación>, el efecto de la palabra clave privada está relacionada con la visibilidad de la unidad que contiene la clase.) La visibilidad de un identificador (p.ej. una variable, un procedimiento, una función o un tipo de datos) es la porción del código en que el identificador es accesible. La regla básica es que un identificador tiene sentido sólo donde es visible — esto es, sólo dentro del bloque en que fue declarada. No se puede usar un identificador fuera de donde es visible. He aquí algunos ejemplos.

Cualquier declaración en la porción de interfaz de una unidad es accesible desde cualquier parte del programa que incluya la unidad en la cláusula uses. Las variables de clases de formulario se declaran del mismo modo, de tal forma que se podrá referir a un formulario (y a sus campos públicos, métodos, propiedades y componentes) desde el código de cualquier otro formulario. Por supuesto, es un hábito de programación poco recomendable declarar todo como global. Aparte de los problemas de ocupación de memoria obvios, usar variables globales hace que el mantenimiento y la actualización del programa sean más difíciles. En resumen, será mejor que use el menor número posible de variables globales.

Unidades como Namespaces

La instrucción uses es la técnica habitual para acceder el marco de vigencia de otra unidad. Con ella podrá acceder a las definiciones de la unidad. Pero podría ocurrir que dos unidades a que se refiere declaren el mismo identificador; esto es, podría encontrarse con dos clases o dos rutinas con el mismo nombre.

En este caso puede, simplemente, usar el nombre de unidad como prefijo del nombre del tipo o rutina definida en aquella. Por ejemplo, puede referirse al procedimiento ComputeTotal definido en la unidad Totals dada como Totals.ComputeTotal. Esto no será necesario muy a menudo, a no ser que incurra en el error de dar el mismo nombre a dos cosad distintas en un programa.

De cualquier manera, si echa un vistazo a la biblioteca VCL y los archivos de Windows, encontrará que algunas funciones Delphi tienen el mismo nombre (pero, en general, distintos parámetros) que ciertas funciones API de Windows disponibles en el mismo Delphi. Un ejemplo es el sencillo procedimiento Beep.

Cree un nuevo programa en Delphi, añada un botón y escriba el siguiente código:

procedure TForm1.Button1Click(Sender: TObject);
begin
  Beep;
end;

Entonces, tan pronto como pulse el botón oirá un breve sonido. Ahora, pase a la instrucción uses de la unidad y modifique ligeramente el aspecto actual del código ...

uses
  Windows, Messages, SysUtils, Classes, ...

... situando la unidad SysUtils antes de la unidad Windows :

uses
  SysUtils, Windows, Messages, Classes, ...

Si, ahora, intenta recompilar este código, dará con un error de compilación: "Not enough actual parameters." (No hay suficientes parámentros actuales). El problema consiste en que la unidad Window define otra función Beep con dos parámetros. Dicho de forma más general, lo que ocurre en las definiciones de las primeras unidades se podría ocultar con definiciones correspondientes en unidades posteriores. La solución segura es, de hecho, bastante simple :

procedure TForm1.Button1Click(Sender: TObject);
begin
  SysUtils.Beep;
end;

Este código se compilará independientemente del orden de las unidades en las instrucciones uses. Aparte de estos, son pocos los conflictos de nombre que aparecen en Delphi, sencillamente porque el código de Delphi está, en general, contenido en métodos de clases. Tener dos métodos con el mismo nombre en clases distintas no crea ningún problema. Los problemas aparecen sólo con las rutinas globales.

Unidades y programas

Una aplicación Delphi consiste en dos tipos de archivo de código fuente: una o más unidades y un archivo de programa. Las unidades se pueden considerar archivos secundarios, a que se puede referir con la parte principal de la aplicación, el programa. En teoría, esto es cierto. En la práctica, el archivo de programa es, habitualmente, un archivo generado de forma automática, y tiene un papel limitado. Sólo tiene que iniciar el programa, ejecutando el formulario principal. El código del archivo de programa, o Delphi project file (DPR) puede ser editado tanto manualmente como usando el Project Manager y alguna de las opciones de proyecto relacionadas con el objeto de la aplicación y los formularios.

La estructura del archivode programa es normalmente mucho más sencilla que la estructura de las unidades. He aquí el código fuente de un archivo de programa que nos sirve de ejemplo :

program Project1;

uses
  Forms,
  Unit1 in ‘Unit1.PAS’ {Form1DateForm};

begin
  Application.Initialize;
  Application.CreateForm (TForm1, Form1);
  Application.Run;
end.

Como se ve, sólo aparece una sección uses y el código principal de la aplicación, encerrada por las palabras clave begin y end. La instrucción uses del programa es especialmente importante, porque se usa para administrar la compilación y el enlazamiento de la aplicación.

Conclusión

Al menos por el momento, este capítulo sobre la estructura de una aplicación Pascal escrita en Delphi o en una de las últimas versiones de Turbo Pascal, es el último del libro. Puede usted enviarme correo electrónico con sus comentarios y peticiones.

Si después de esta introducción al lenguaje Pascal quiere sumergirse en los elementos orientados a objeto del Object Pascal de Delphi, puede consultar mi libro Mastering Delphi 5 (Sybex, 1999) [N. del T.: La traducción al español de Mastering Delphi 4 está disponible bajo el título Delphi 4]. Para más información sobre estos y otros libros avanzados escritos por mí (y otros autores) puede consultar mi sitio en la Red, www.marcocantu.com. El mismo sitio mantiene versiones actualizadas de este libro y de los ejemplos de código que aparecen en él.

Volver a la página principal

© Copyright Marco Cantù, Wintech Italia Srl 1995-99
© Copyright de la traducción, Rafael Barranco-Droege, 2000