Delphi OOP-Cap 01

download Delphi OOP-Cap 01

If you can't read please download the document

Transcript of Delphi OOP-Cap 01

Creado el 16/06/09

Aprendiendo OOP con Delphi

Pgina 1 de 32

Creado el 16/06/09

1 Introduccin alas bases de la POO

Conceptos Principales: Introduccin a:

Bases de la orientacin a objetos Estructura de Unidad (Unit) y estructura de Proyecto Generacin del RAD de Delphi: objetos visuales y eventos Manejadores de eventos Creacin de un objeto (mediante RAD y cdigo) Definiendo una clase Declarando una referencia a un objeto Instanciando un objeto Liberando un objeto Interaccin entre objetos: paso simple de mensaje, asociacin y composicin El UML: diagramas de clase, objeto y secuencia Relaciones entre herencia, asociacin y composicin

Aprendiendo OOP con Delphi

Pgina 2 de 32

Creado el 16/06/09

IntroduccinLa Orientacin a Objetos (OO) puede ser vista desde tres diferentes aspectos: objetos como entidades independientes, objectos como entidades derivadas y objetos como entidades que interactan.

Objetos como Entidades IndependientesUn objeto es una entidad separada, contenida en s misma y encapsulada, y el concepto de encapsulacin es importante en la POO. Esto significa que un objeto tiene datos que pueden mantenerse privados respecto al mundo exterior y que tiene unas caractersticas especficas. Manipula sus datos e implementa sta capacidad a travs de sus mtodos. La escritura del cdigo que define los mtodos de un objeto tiene muchas similitudes con la programacin estructurada, y de hecho utiliza muchos de los principios de la programacin estructurada, tales como la seleccin estructurada (If..then..else, Case) y la repeticin (While..do y bucles For). En ste mdulo asumimos que el estudiante est familiarizado con estos conceptos, as que nos concentraremos en los principios que se aplican especficamente a la programacin orientada a objetos (POO).

Objectos como Entidades DerivadasLa reutilizacin es una consideracin muy importante en la POO. Si algunas operaciones requeridas o almacenamientos de datos ya existen en una clase, es posible para otra clase tomar ventaja de stas operaciones y datos y as evitar recodificarlos. La POO posibilita ste segundo aspecto, una derivacin de clase desde otras clases, posible a travs de las subclases (el uso de la herencia) y a travs de la composicin, y puede reducir significativamente la cantidad de cdigo que uno necesita escribir.

Objetos como Entidades que InteractanEl tercer aspecto, la interaccin entre objetos, depende de la asociacin y el subtipado. Si los objetos no pueden interactuar, no pueden cooperar con los dems para realizar las tareas requeridas en un programa de ordenador. As que el programador crea asociaciones (enlaces) entre objetos para enviar mensajes de unos a otros. Para permitir que stas interacciones conduzcan a diferentes resultados bajo distintas circunstancias, el programador puede usar el subtipado y el polimorfismo. El subtipado es cuando los objetos dentro de la misma jerarqua implementan sus interfaces comunes de forma diferente, y esto se ver ms en profundidad ms tarde en ste captulo. Existe una considerable interpolacin entre estos aspectos. La derivacin y la interaccin de objetos ambas usan la herencia, la cual est directamente soportada en el lenguaje de programacin, y las formas de enlazado de objetos (asociacin y composicin), no estn directamente soportadas por los constructores del lenguaje.

Representando Sistemas OO: UMLEs til poder representar un programa de una forma grfica, compacta, como alternativa al cdigo actual. ste mdulo usa un subjuego del Unified Modelling Language (UML). El UML1 proporciona un juego de diagramas integrados y estndares que son ampliamente utilizados. En ste mdulo nos concentraremos en los diagramas de clases, objetos y secuencias para capturar los aspectos dinmicos y estticos de los programas y para presentar los principios subyancentes de la POO.

1

http://es.wikipedia.org/wiki/UML

Aprendiendo OOP con Delphi

Pgina 3 de 32

Creado el 16/06/09

Patrones: Aplicando Principios OOMientras que los principios bsicos de la POO son realmente sencillos, sus aplicaciones pueden volverse extremadamente sofisticadas. Los miembros de la comunidad OO han adoptado el concepto de Patrones de Software para capturar sta experiencia, combinando el conocimiento de muchos programadores OO expertos. ste mdulo lleva al estudiante a travs de varios e importantes Patrones de Software, utilizndolos para resolver problemas especficos y para ver la mejor manera de aplicar los principios generales de la POO. La programacin es difcil, y la programacin orientada a objetos lo es ms an. Una tpica aproximacin es proporcionar a los alumnos un juego de clases preconstrudas (p.ej., una caja de herramientas de grficos) como punto de inicio para la programacin OO. ste mdulo adopta una variacin sobre sta aproximacin usando Delphi, un generador RAD GUI (Rapid Application Development, Graphical User Interface) con una amplia librera de componentes GUI. sta librera permite a los alumnos construir sus propios objetos visuales para usarlos y manipularlos en sus programas. sta librera estndar de objetos de interfaz de usuario y el entorno visual de generacin de cdigo (GUI) proporcionan un vehculo natural para demostrar los principios subyacentes y para concretar conceptos OO, y es un buen punto de entrada en las complejidades de la programacin OO. Esto ayudar a clarificar cuestiones como la anatoma de una clase, la combinacin de clases existentes para crear una nueva clase y la reutilizacin a travs de la herencia, tomando ventaja de caractersticas tales como la Visual Component Library (VCL) y la Visual Form Inheritance (VFI). El primer captulo usa el generador GUI de Delphi para comenzar a ver la estructura interna de un objeto. El segundo captulo analiza la herencia generada va RAD y la jerarqua de componentes estndar de interfaz de usuario. El tercer captulo ayuda a los programadores OO novatos a escribir clases generadas por el programador y el cuarto captulo analiza las formas de acceder a un objeto y a sus datos. El captulo dos introduce la herencia para la reutilizacin, a travs de las subclases, presentando al VFI y a la librera VCL suministradas con Delphi. La herencia tambin proporciona la posibilidad del subtipado y el poder del polimorfismo, y esto es introducido en los captulos cuatro y cinco, usando el parmetro estndar de Delphi Sender como punto de inicio. El captulo seis rene el material de los captulos anteriores, estableciendo varios antipatrones que ponen de relieve fallos potenciales al usar la herencia. Junto con el polimorfismo, el concepto de objetos cooperantes es crucial en la POO. La cooperacin entre objetos de diversas formas es un tema que comienza a verse en el captulo siete hasta el final del mdulo.

Aprendiendo OOP con Delphi

Pgina 4 de 32

Creado el 16/06/09

Los conceptos de polimorfismo y cooperacin son consolidados mediante la exploracin, a partir del captulo nueve, de una variedad de patrones OO. La siguiente tabla muestra los patrones que cubriremos en ste mdulo junto con los conceptos de POO que estos patrones nos permiten explorar:Patrn Inmutable Argumento Sender Adaptador Conceptos

Encapsulacin y visibilidad (campos private, protected y public) Bajo Acoplamiento Retorno de Llamada Reutilizacin Delegacin Implcita Activacin de la sustitucin con clases no relacionadas Bajo Acoplamiento Delegacin Implcita Empaquetado para simplificacin Bajo Acoplamiento Delegacin Implcita Definicin de Clase, distinguiendo entre atributos y roles Delegacin Empaquetado para futura evolucin Cambiando asociaciones dinmicamente Empaquetado para variabilidad (reduccin de acoplamiento) Sustitucin Polimrfica Empaquetado para variabilidad (reduccin de acoplamiento) Sustitucin Polimrfica Implementacin a diferentes niveles jerrquicos Definicin de Clase Informacin de Enlace (asociacin) Manufactura de Objecto Separacin de Capacidades (SoC2) Manufactura de Objecto Clases y campos de datos de objetos Recursin Polimrfica

Fachada

Ley de Demetrio Rol del Jugador

Estrategia Mtodo Plantilla

Clase Asociacin Mtodo Factora y Factora Abstracta Singleton Mono State Decorador

Mientras contrastemos la subclase y el subtipado tambin consideraremos distintos antipatrones de herencia. Los principios fundamentales de los patrones son presentados textual y grficamente (a travs de palabras y diagramas de clase UML, diagramas de objectos y diagramas de secuencias) y la implementacin a travs de ejemplos prcticos detallados, permitiendo al estudiante consolidar los conceptos considerando dos perspectivas diferentes. El uso de estos diagramas proporciona familiaridad en la lectura de clases, objetos y diagramas de secuencias. Esto ayuda a desarrollar las bases de la representacin e indica algunas de sus fortalezas y limitaciones. Este curso utiliza Delphi para ensear la orientacin a objetos. La base de Delphi es Pascal. ste tambin est fuertemente orientado a objetos y proporciona muchas caractersticas OO tales como la herencia de clase, enlazado esttico y dinmico y referencias semnticas.

2

En ciencias de la computacin, la Separacin de Capacidades (SoC) es el proceso de dividir un programa de ordenador en distintas funciones que se solapan en funcionalidad lo menos posible. Una capacidad es cualquier pieza de inters o atencin en un programa. Normalmente, las capacidades son sinnimo de caractersticas o comportamientos. El progreso hacia SoC es tradicionalmente logrado a travs de la modularidad y la encapsulacin, con la finalidad de ocultar informacin.

Aprendiendo OOP con Delphi

Pgina 5 de 32

Creado el 16/06/09

El mdulo hace un uso extensivo de ejemplos prcticos y clasificados, para dar al estudiante experiencia prctica en la implementacin de cdigo OO. Esto ayuda a reducir la brecha entre los principios aparentemente simples de la POO y las ramificaciones de estos principios en la prctica. A travs de la secuencia de conceptos y del uso extensivo de ejemplos prcticos, ste mdulo apoya firmemente el estudio independiente, y se ha preparado con el objetivo de posibilitar el estudio a distancia. En los dos primeros captulos de ste mdulo usamos capacidades del RAD de Delphi para comenzar la exploracin de varios aspectos de la POO. Luego aplicamos estos mismos principios al cdigo que escribimos. Comenzamos a explorar cmo definir e instanciar clases viendo la forma en que Delphi construye un formulario o Form, el cual es el nombre que Delphi usa para una ventana en un entorno de interfaz grfico.

Ejemplo 1.1. Un archivo UnitDelphi se estructura alrededor del concepto de objetos. Un formulario o form es un objeto, y los distintos componentes que colocamos en un form tambin son objetos. Para comenzar a investigar sobre las clases y objetos del RAD de Delphi, abra una nueva aplicacin (File | New | Application hasta Delphi 7; File | New | VCL Forms Application para Delphi > 7). Usando la secuencia de men View | Units | Unit1, mire el cdigo de Unit1. Distintas versiones de Delphi mostrarn pequeas diferencias: en Delphi versin 2006 se ve as:1 unit Unit1; 2 interface 3 uses 4 Windows, Messages, SysUtils, Variants, Classes, 5 Graphics, Controls, Forms, Dialogs; 6 type 7 TForm1 = class(TForm) 8 private 9 { Private declarations } 10 public 11 { Public declarations } 12 end; 13 var 14 Form1: Tform1; 15 implementation 16 {$R *.dfm} 17 end.

Nota: Las versiones de Delphi > 7 ofrecen la eleccin entre Forms VCL (que da compatibilidad con versiones anteriores), Forms de Windows y ASP.NET. Ya que los principios OO con los que vamos a trabajar con independientes del tipo de Form que usemos, utilizaremos formularios VCL para que sea ms sencillo moverse entre distintas versiones.

Los programas Delphi pueden contener muchos archivos de unidad (unit). La estructura bsica de un archivo unit comprende tres secciones, el nombre de la unit (como vemos en la lnea 1 del cdigo anterior), la seccin de interfaz (lneas 214) y la seccin de implementacin (lneas 1517).Aprendiendo OOP con Delphi Pgina 6 de 32

Creado el 16/06/09

El Nombre de la UnidadPor defecto, Delphi asigna a la primera unidad el nombre Unit1 (lnea 1). Consecuentemente llama al resto de unidades Unit2, Unit3, y as en adelante. Cuando almacenamos el archivo bajo un nuevo nombre (p.ej., con la secuencia de men File | Save As...), Delphi cambia el nombre de la unit y mantiene una referencia cruzada al archivo en el archivo de proyecto (.dpr o .bdsproj).

La Seccin de InterfazLa seccin de interfaz (lneas 214) proporciona un enlace entre una determinada unit y otras units, y consiste en varias subsecciones: la clusula uses (lneas 35), las declaraciones type (lneas 612) y las declaraciones de variables globales (lneas 1314) (las declaraciones de constantes globales, que no tenemos aqu, son similares a las declaraciones de variables globales). La clusula uses (lneas 35): en orden a su funcionamiento, un programa Delphi necesita un montn de informacin de fondo desde varios ficheros unit que son parte estndar de Delphi. Por ejemplo, si el archivo SysUtils (lnea 4) no estuviera en la lista de uses, no podramos realizar ninguna operacin con cadenas. Como parte del soporte de su RAD, Delphi automticamente lista las units adicionales que la interfaz de usuario necesita bajo la clusula uses. La declaracin de tipos (lneas 612): en los lenguajes de programacin orientada a objetos, un tipo o clase define una estructura o plantilla que podemos usar en nuestro programa para crear (instanciar) un objeto que necesitamos. Aqu estamos definiendo una clase de interfaz de usuario y Delphi genera el cdigo para la clase del Form automticamente, a travs de sus capacidades RAD. La lnea 6 del cdigo anterior notifica al compilador que a continuacin vienen las declaraciones de tipo (clases). En ste programa declaramos slo una clase, TForm1, pero podemos declarar clases adicionales, tanto en una misma unit como en distintas units. La lnea 7 deriva una nueva clase, llamada TForm1, desde TForm. TForm es una clase estndar de Delphi y es la plantilla para el formulario en blanco que aparece cuando iniciamos una nueva aplicacin. La clase estndar TForm tiene muchas capacidades incorporadas dentro de ella. Por ejemplo, sabe (a travs de sus mtodos) cmo crearse a s misma y cmo mostrarse a s misma en pantalla. Tambin tiene propiedades como Caption, Height y Width. Gracias a la lnea 7 nosotros heredamos todas stas capacidades desde TForm como punto de comienzo para nuestra propia clase, TForm1. De momento an tenemos slo el formulario en blanco y no lo ampliaremos de ninguna manera. Dentro de poco, cuando aadamos algunos componentes y manejadores de eventos, veremos cmo Delphi utiliza sus capacidades RAD para aadir estos objetos y mtodos a la declaracin de tipos de TForm1. La declaracin de variables (var) (lneas 13 y 14): la subseccin previa, la declaracin de tipos, proporciona las clases adicionales que definimos en nuestro programa. Sin embargo, un tipo es slo una plantilla y no un objeto. En sta seccin, en la declaracin var, nosotros declaramos qu objetos crearemos desde las clases disponibles. Esta accin establece la reserva de memoria en la pila para referenciar a estos objetos. El nico objeto hasta la fecha es el form que Delphi crea automticamente cuando iniciamos un nuevo proyecto. ste es el llamado Form1, y es de tipo TForm1 (lnea 14). Para ayudarnos a mantener la distincin entre el tipo y el objeto, Delphi tiene las convenciones de iniciar los nombres de tipo con una T. As, TForm1 es el tipo y Form1 es el objeto.

Aprendiendo OOP con Delphi

Pgina 7 de 32

Creado el 16/06/09

La Seccin de ImplementacinLa tercera parte de una unit es la seccin de implementacin. Aqu es donde nosotros escribimos nuestro cdigo de programa. Debido a que an no hemos escrito ninguna rutina la seccin de implementacin est vaca, excepto por la existencia de una directiva del compilador {$R *.DFM} (lnea 16). A primera vista, las llaves que encierran a la directiva del compilador le dan a sta la apariencia de un comentario, as que podramos estar tentados de borrar la lnea. NO LO HAGA! El smbolo de apertura aqu es el smbolo compuesto {$ que indica que no es un comentario convencional sino que en su lugar es una instruccin especial para el compilador. {$R *.DFM} es una directiva de recurso que le dice al compilador que incluya el fichero del form (el fichero .dfm) en la aplicacin. As que no elimine sta lnea. Una opcional y local clusula uses y declaraciones a nivel de unit de constantes y variables, no presentes aqu, pueden aparecer seguidos por las necesarias definiciones de mtodos (el Ejemplo 1.3, paso 2, lnea 17 muestra una clusula local uses). A diferencia de la seccin de interfaz, la cual hace posible la comunicacin con otras units, la seccin de implementacin es privada y slo para la unit. En ella se describe el funcionamiento interno de todas las clases declaradas en la declaracin de tipo.

Ejemplo 1.1. SumarioEl fichero unit tiene un nombre para identificarse a s mismo, una seccin de interfaz para comunicar con otras units y una seccin de implementacin que contiene los detalles privados del funcionamiento de la unit. La seccin de interfaz contiene la clusula global uses, la declaracin de tipos y las declaraciones de constantes y variables globales. La seccin de implementacin contiene la clusula local uses, las declaraciones de constantes y variables locales y las definiciones de mtodos. Delphi automticamente crea un esqueleto para la nueva clase TForm1 que estamos creando. Utiliza la clase estndar TForm como base para la nueva clase TForm1 derivando TForm1 desde TForm.

Ejemplo 1.2. Extendiendo una Aplicacin VacaEntre las diversas capacidades RAD que Delphi ofrece se encuentra un constructor visual para interfaces grficas de usuario (GUIs). Esto simplifica enormemente la construccin de una interfaz de usuario y permite al programador concentrarse en la programacin. En ste ejemplo veremos brevemente el proceso de construccin del GUI para escribir un programa con dos botones. Picando en uno cambia el fondo del form a amarillo, y picando en el otro cambia el fondo a azul (Figura 1).

Ejemplo 1.2 paso 1. un constructor de GUI via RAD

Figura 1: Un sencillo programa Delphi

En ste ejemplo crearemos un sencillo programa Delphi y veremos el cdigo generado va RAD en el listado de units. Comience una nueva aplicacin y aada dos botones al form (Figura 1). Para cambiar el nombre de la unit, grbela como TwoButtonsU.pas (usando la secuencia de men File | Save As).Aprendiendo OOP con Delphi Pgina 8 de 32

Creado el 16/06/09

Ahora inicialice algunas propiedades de los objetos GUI con el Inspector de Objetos y vea cmo cambian en el diseo del form. Una forma de presentar las propiedades es a travs de una tabla:Componente Form Button1 Button2 Propiedad Name Caption Name Caption Name Caption Valor FrmStructureDemo Unit Structure btnYellow &Yellow btnBlue &Blue

Delphi almacena las propiedades iniciales en un fichero .dfm. Trasladando sta tabla de propiedades al formato dfm tenemos lo siguiente:object frmStructureDemo: TfrmStructureDemo Caption = ' Unit Structure' object btnYellow: TButton Caption = '&Yellow' object btnBlue: TButton Caption = '&Blue'

Delphi 6 y 7 muestran la estructura del objeto interfaz de usuario en el Object TreeView (Figura 2) (El Model View de Delphi 8/2005 da similar funcionalidad). Esto nos da la jerarqua de contenidos, no la jerarqua de herencia, y muestra que el objeto del form frmStructureDemo contiene dos botones, btnBlue y btnYellow (como veremos ms tarde, Delphi implementa este contenido a travs de una forma dura de agregacin llamada composicin).

Ejemplo 1.2 paso 2. Eventos y sus ManejadoresEl GUI interacta con el cdigo de programa a travs de los eventos. El form mismo y cada uno de los objetos en el form pueden dar lugar a una serie de diferentes eventos, ya sea en respuesta a acciones del usuario o a ocurrencias del sistema. Uno de los eventos ms comunes es el evento OnClick, el cual es generado cuando el usuario hace click con el ratn sobre un objeto visual. En ste paso escribiremos manejadores para el evento OnClick para cada uno de los botones. Haga doble click sobre btnBlue. El generador RAD de Delphi inserta un esqueleto de manejador de eventos en el cdigo de programa y enlaza el evento OnClick a ste manejador. Inserte el cdigo de programa requerido (lnea 27 debajo) y luego haga doble click sobre btnYellow e inserte su cdigo de programa (lnea 23) antes de salvar la unit (File | Save As) como TwoButtonsU y entonces el fichero de proyecto (File | Save Project As) como TwoButtonsP. Ejecute el programa ( o Run | Run). Pulsar sobre el botn Blue hace que el form se vuelva azul (lnea 27), mientras que el botn Yellow hace que el form se vuelva amarillo (lnea 23).1 unit TwoButtonsU; 2 interface 3 uses 4 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, 5 Dialogs, StdCtrls; 6 type 7 TfrmStructureDemo = class(TForm) 8 btnYellow: TButton; 9 btnPurple: TButton; 10 procedure btnYellowClick(Sender: TObject); 11 procedure btnBlueClick(Sender: TObject); 12 private

Aprendiendo OOP con Delphi

Pgina 9 de 32

Creado el 16/06/09

13 { Private declarations } 14 public 15 { Public declarations } 16 end; 17 var 18 frmStructureDemo: TfrmStructureDemo; 19 implementation 20 {$R *.DFM} 21 procedure TfrmStructureDemo.btnYellowClick(Sender: TObject); 22 begin 23 frmStructureDemo.Color := clYellow; 24 end; 25 procedure TfrmStructureDemo.btnBlueClick(Sender: TObject); 26 begin 27 frmStructureDemo.Color := clBlue; 28 end; 29 end.

Figura 2: El Objetct TreeView mostrando los botones que componen el form

Ejemplo 1.2 paso 3. Analizando el Cdigo Generado va RADAhora investigaremos varios aspectos del cdigo generado mediante RAD.

Cambiando el Nombre de la UnitCuando almacenamos la unit como TwoButtonsU, Delphi cambi el nombre de la unit de Unit1 a TwoButtonsU (lnea 1 arriba). Para mantener el seguimiento de proyecto sincronizado, cambie siempre el nombre de una unit a travs de Save As y no cambie el nombre directamente en el cdigo de programa.

Cambiando el Nombre del FormEn el Inspector de Objetos cambiamos el nombre del form a frmStructureDemo. Sobre sta base, Delphi cambi el nombre del nuevo tipo de formulario a TfrmStructureDemo (ste todava est derivado desde TForm, lnea 7). Delphi entonces declar el objeto formulario como frmStructureDemo (sin el prefijo T) de tipo TfrmStructureDemo (con el prefijo T) (lnea 18) (la declaracin de variable de la lnea 18 significa que podemos usar frmStructureDemo para referirnos a un objeto de tipo TfrmStructureDemo).

Aprendiendo OOP con Delphi

Pgina 10 de 32

Creado el 16/06/09

Aadiendo BotonesAadimos dos botones al formulario y les llamamos btnYellow y btnBlue. Sobre sta base, Delphi automticamente insert las lneas 8 y 9. Estas declaran que la clase TfrmStructureDemo est compuesta de dos objetos llamados btnYellow y btnBlue, ambos del tipo TButton (clase estndar para botones de Delphi). Estos objetos son ahora parte del tipo TfrmStructureDemo como se refleja en el Object TreeView (Figura 2). Al componer una clase, en ste caso TfrmStructureDemo, desde otros objetos, en ste caso btnYellow y btnBlue de tipo TButton, obtenemos automticamente todas las capacidades de la clase TButton cuando la inclumos en nuestro formulario. Como TForm, TButton es una clase estndar de Delphi, y la composicin nos brinda una potente forma de reutilizar componentes y clases existentes. Retornaremos a ste concepto de la composicin en ms detalle cuando lo usemos como herramienta para crear nuestras propias clases.

Aadiendo Manejadores de EventoAadimos un mtodo manejador del evento3 OnClick para cada botn haciendo doble click en cada uno de ellos en el diseador del form4 y aadiendo el cdigo necesario. Delphi automticamente extiende la definicin de clase. Incorpora estos manejadores de evento como mtodos del TfrmStructureDemo declarando estos procedimientos en la estrutura de tipo (type) (lneas 10 y 11 arriba). Estas declaraciones no definen lo que hacen los procedimientos, por lo que Delphi tambin crea los esqueletos para estos manejadores de evento en la seccin de implementacin (implementation) (lneas 21 a 28), dejando que los rellenemos con el cdigo de programa que sea necesario (lneas 23 y 27). En Delphi Pascal, aunque los mtodos pueden ser tanto procedimientos como funciones, los manejadores de evento son siempre procedimientos. Junto con todos los mtodos de las clases TForm y TButton, estos manejadores de evento ahora son tambin mtodos que pertenecen a la clase TfrmStructureDemo. Una declaracin de mtodo, como la de la lnea 10, es a veces denominada firma o signatura de mtodo, ya que nos da el nombre del mtodo ( btnYellowClick), el tipo de subrutina (un procedimiento) y la lista de parmetros (Sender: TObject). Cuando nos pongamos a definir y usar nuestras propias clases y objetos comenzaremos por imitar el cdigo RAD de Delphi.

Ejemplo 1.2 paso 4. Una Representacin Grfica: UMLCuando diseamos y documentamos un programa, puede ser muy til usar una representacin grfica de su estructura y funcionamiento. Un ampliamente usado lenguaje de modelado grfico OO es el Unified Modelling Language, o UML, y eso es lo que usaremos aqu. El UML representa una clase como un caja o cuadro con un nmero determinado de compartimentos (Figura 3). El compartimento superior nos da el nombre de la clase (comprelo con la lnea 7 en el programa anterior). El segundo compartimento nos da los atributos de la clase (compare con las lneas 8 y 9) y el tercero nos da los mtodos (compare con lneas 10 y 11).

3 4

Por simplicidad, un mtodo manejador de evento es frecuentemente llamado slo un manejador de evento. El Diseador del Form se refiere al formulario cuando est en modo diseo.

Aprendiendo OOP con Delphi

Pgina 11 de 32

Creado el 16/06/09

Figura 3: Un diagrama UML de clase

Un diagrama de clase UML tambin puede mostrar relaciones entre clases, tales como la herencia y la asociacin. Primero veremos la herencia o generalizacin, como es llamada en UML. Esta es mostrada con una punta de flecha cerrada apuntando desde la subclase a la superclase (Figura 4, compare con lnea 7 anterior). Las clases se pueden volver complejas y por ello uno generalmente muestra slo aquellos atributos y mtodos que son de inters en un particular diagrama. En la Figura 4, mostramos TForm sin ninguno de sus atributos o mtodos. Debido a que la subclase es todo lo que es la superclase y algo ms, la herencia es frecuentemente llamada una relacin IsA (EsUn).

Figura 4: Herencia (generalizacin) en UML

En adicin a la relacin de herencia (o generalizacin, en UML), tambin podemos usar el UML para mostrar las varias formas de asociacin. Una forma estricta de asociacin es la composicin. Mencionamos antes que las relaciones entre el formulario y los dos botones es composicin. Por tanto, en vez de mostrar los dos botones como atributos del formulario en la Figura 4, podemos mostrar la clase TButton separadamente y mostrar entonces que TfrmStructureDemo usa (est compuesto por) dos TButtons como en la Figura 5. La representacin UML para la composicin es un diamante slido en la clase compuesta conectado por una lnea a la clase o clases que usa la clase compuesta. Aunque TfrmStructureDemo est compuesto por dos Tbuttons, nosotros mostramos la clase TButton slo una vez, pero inclumos un multiplicador 1:2 en el enlace compuesto. Debido a que mostramos los TButtons por separado, ya no los inclumos ms dentro de la caja que representa los atributos de TfrmStructureDemo.

Aprendiendo OOP con Delphi

Pgina 12 de 32

Creado el 16/06/09

Figura 5: Mostrando la composicin en un diagrama de clase

UML

Ejemplo 1.2. SumarioComo base para crear nuestras propias clases en el futuro hemos analizado cmo Delphi aade campos de datos (los botones) y mtodos (los manejadores de evento) a una definicin de clase. El UML proporciona diagramas de clase para representar la estructura de clases y la herencia y la composicin entre ellas.

Ejemplo 1.3. Orientacin a ObjetosLos objetos interactan unos con otros, y como vamos a ver durante el transcurso de ste mdulo, una forma de ver un programa orientado a objetos es como un grupo de objetos encapsulados que cooperan, a travs del paso de mensajes, para proporcionar un determinado juego de servicios. Para demostrar esto, en ste ejemplo crearemos dos clases, cada una en una unit separada, con paso de mensaje simple unidireccional (pasos 1 y 2 siguientes). Este enlace es un ejemplo de asociacin, con un objeto solicitando un servicio de otro objeto, y es a veces llamado un relacin de tipo UsaUn (UsesA). En el paso 3 veremos cmo Delphi empaqueta un programa que consiste en ms de una unit. Los diagramas UML proporcionan una importante manera de resumir y visualizar los que est ocurriendo en un programa OO, y los pasos 4, 5 y 6 presentan los diagramas de clase, objeto y secuencia para ste programa. A veces, el objeto A puede requerir un servicio de un objeto B, pero el objeto B todava no existe. Bajo stas circunstancias, el objeto A especficamente crea (instancia) al objeto B, obteniendo los servicios requeridos del objeto B, y luego destruye al objeto B cuando no lo necesita ms. El paso 7 modifica el programa para dar una simple ilustracin del proceso.

Ejemplo 1.3 paso 1. Un Form PrincipalPara ilustrar mensajes simples, crearemos dos clases, cada una en su propia unit. En ste paso definimos (figuras 6 y 7), el cual enva mensajes a TfrmAuxiliary para mostrarse y ocultarse a s mismo (lneas 24 y 28 debajo). TfrmAuxiliary ser definido en el paso 2. Debido a que TfrmMain usar TfrmAuxiliary,la unit MainForm debe listar a la unit AuxForm, la unit que contiene a TfrmAuxiliary, en una clusula uses. Aqu seleccionamos usar una clusula uses local (lnea 20).TfrmMain

Aprendiendo OOP con Delphi

Pgina 13 de 32

Creado el 16/06/09

Figura 7: los objetos de la interfaz de Figura 6: El form principal usuario que forman el form principal

1 unit MainForm; 2 interface 3 uses 4 Windows, Messages, SysUtils, Variants, Classes, Graphics, 5 Controls, Forms, Dialogs, StdCtrls; 6 type 7 TfrmMain = class(TForm) 8 radAuxShow: TRadioButton; 9 radAuxHide: TRadioButton; 10 procedure radAuxShowClick(Sender: TObject); 11 procedure radAuxHideClick(Sender: TObject); 12 private 13 { Private declarations } 14 public 15 { Public declarations } 16 end; 17 var 18 frmMain: TfrmMain; 19 implementation 20 uses AuxForm; 21 {$R *.dfm} 22 procedure TfrmMain.radAuxShowClick(Sender: TObject); 23 begin 24 frmAuxiliary.Show; 25 end; // end procedure TfrmMain.radAuxShowClick 26 procedure TfrmMain.radAuxHideClick(Sender: TObject); 27 begin 28 frmAuxiliary.Hide; 29 end; // end procedure TfrmMain.radAuxHideClick 30 end. // end unit MainForm

Los mensajes de llamada aparecen en las lneas 24 y 28. Estos consisten en el objeto destinatario de la llamada seguido por un punto y finalizando en un nombre de mensaje (definimos frmAuxiliary en el siguiente paso para ste ejemplo). Los mensajes de llamada se parecen a las subrutinas de llamada (lneas 24 y 28 anteriores). La diferencia entre las dos es que los mensajes de llamada permiten polimorfismo. El polimorfismo es un aspecto importante de la POO que permite a distintos objetos responder de forma diferente al mismo mensaje. Esto, por ejemplo, permite a los programas OO responder apropiadamente a condiciones variantes sin la necesidad de complejos juegos de lneas de cdigo de estamentos condicionales.Aprendiendo OOP con Delphi Pgina 14 de 32

Creado el 16/06/09

Delphi automticamente hace provisin para campos de datos pblicos y privados en el form (lneas 12 a 15). En ste ejemplo no hay adicionales campos pblicos o privados, y por ello estos estamentos no realizan ninguna funcin. Ellos recuerdan a los programadores que es posible aadir declaraciones pblicas y privadas a un formulario RAD, y lo haremos de vez en cuando. Sin embargo, a menudo no tendremos ninguna declaracin pblica o privada que aadir, y por ello eliminaremos esas lneas de nuestro cdigo para evitar engordar los ejemplos.

Ejemplo 1.3 paso 2. Un Form AuxiliarAada un segundo formulario al proyecto. ste consistir en un formulario en blanco, TfrmAuxiliary, sin ningn otro componente (figuras 8 y 9). ste hereda la habilidad de mostrarse y ocultarse a s mismo desde Tform, la clase librera desde la cual todos los formularios son derivados (lnea 7 debajo). Usamos el manejador de evento OnShow (lneas 14 a 18) para definir un comportamiento adicional a TfrmAuxiliary: ste establece la posicin en la pantalla aleatoriamente cada vez que el formulario es mostrado (lneas 16 y 17). 1. El generador de nmero aleatorio necesita ser ubicado y escogemos colocarlo en la seccin de inicializacin (lneas 1920): podramos tambin haber colocado el estamento Randomize en el manejador de evento OnCreate del form. En cualquier unit la seccin de inicializacin (initialization) es opcional. Si est presente, los estamentos en la seccin se ejecutan cuando el programa se inicia, antes que cualesquiera otros estamentos que hayan en esa unit. Comienza con la palabra reservada initialization y contina hasta el comienzo de la seccin finalization o, si no hay seccin de finalizacin, hasta el final de la unit. Si hay varias units en un proyecto, las distintas secciones de inicializacin se ejecutan en el orden en que las units aparecen el el fichero de proyecto. Si una unit usa otras units, sus secciones de inicializacin se ejecutan antes de que ellas lo hagan, con las units en la seccin de la clusula uses de la interfaz ejecutndose antes que ellas en la seccin de implementacin.

Figura 8: El form auxiliar

Figura 9: Componentes que componen el form auxiliar

Aprendiendo OOP con Delphi

Pgina 15 de 32

Creado el 16/06/09

1 unit AuxForm; 2 interface 3 uses 4 Windows, Messages, SysUtils, Variants, Classes, Graphics, 5 Controls, Forms, Dialogs, StdCtrls; 6 type 7 TfrmAuxiliary = class(TForm) 8 procedure FormShow(Sender: TObject); 9 end; 10 var 11 frmAuxiliary: TfrmAuxiliary; 12 implementation 13 {$R *.dfm} 14 procedure TfrmAuxiliary.FormShow(Sender: TObject); 15 begin 16 Left := Random (600); 17 Top := Random (400); 18 end; // end procedure TfrmAuxiliary.FormShow 19 initialization 20 Randomize;

21 end. // end unit AuxForm

(Las posiciones de pantalla y referencias en las lneas 16 y 17 se refieren a una pantalla de baja resolucin. Si est usando un monitor de resolucin mayor puede que desee incrementar esos valores proporcionalmente).

Ejemplo 1.3 paso 3. El Fichero de ProyectoDelphi mantiene un registro de las distintas unit que hay en un programa a travs del fichero de proyecto. Para ver el fichero de proyecto para ste ejemplo, use View | Units | Project1.1 program TwoUnits; 2 uses 3 Forms, 4 MainForm in 'MainForm.pas' {frmMain}, 5 AuxForm in 'AuxForm.pas' {frmAuxiliary}; 6 {$R *.res} 7 begin 8 Application.Initialize; 9 Application.CreateForm(TfrmMain, frmMain); 10 Application.CreateForm(TfrmAuxiliary, frmAuxiliary); 11 Application.Run; 12 end.

Las lneas 910 causan la autocreacin de los dos objetos formulario en ste proyecto.

Aprendiendo OOP con Delphi

Pgina 16 de 32

Creado el 16/06/09

Ejemplo 1.3 paso 4. Un diagrama de clases UML coincidenteEl diagrama de clases para las clases definidas en las units MainForm y AuxForm muestra que ambas clases derivan desde TForm (Figura 10). Ni TfrmMain ni TfrmAux declaran ms atributos adicionales, as que dejaremos el compartimento del medio vaco para ambos. Manipulamos sus atributos Left y Top en el programa. Ellos son heredados desde Tform, y por tanto los mostraremos en el compatimento del medio de TForm ya que son atributos (TForm no define actualmente estos atributos por s mismo sino que en su lugar los hereda de TControl, una de sus superclases. Pero ste detalle no es significativo ahora).

Figura 10: Diagrama de clases para el ejemplo 1.3, pasos 1 y 2

Ejemplo 1.3 paso 5. Un Diagrama de Objetos UML CoincidenteLos diagramas de clases tales como el de la Figura 10 son muy comunes, ya que muestran la estructura de un programa. A veces esto tambin es til para tener una instantnea de la situacin de una parte del programa para mostrar qu objetos existen en el momento de la instantnea y cul es su estado (p.ej., los valores de sus atributos). Un diagrama de objetos UML tiene dos compartimentos. El compartimento superior muestra el nombre del objeto y su clase, todo subrayado para enfatizar que es un objeto y no una clase. El segundo compartimento lista los atributos y sus valores en el momento de tomar la instantnea. En ste ejemplo, el programa crea dos objetos al inicio y los destruye cuando el programa finaliza. Los valores en frmMain para Left y Top vienen de los valores establecidos en el Inspector de Objetos y los valores en frmAuxiliary Left y Top son establecidos en el manejador de eventos OnShow. Hay un enlace de comunicacin desde frmMain a frmAuxiliary, y por tanto tenemos el diagrama de objetos mostrado en la Figura 11.

Figura 11: El diagrama de objetos para el ejemplo 1.3, pasos 1 y2

Aprendiendo OOP con Delphi

Pgina 17 de 32

Creado el 16/06/09

Debido a que frmMain interacta con frmAuxiliary, mostramos una asociacin desde frmMain hacia frmAux. La flecha apunta desde frmMain al otro formulario porque frmMain conoce y utiliza ste formulario (lneas 20, 24 y 28 en la unit MainForm). Sin embargo, frmAuxiliary no tiene conocimiento de frmMain por lo que no hay punta de flecha desde frmAuxiliary a frmMain. Debido a que esto es una relacin de asociacin y no de herencia usamos una punta de flecha abierta y no cerrada. La asociacin, como la herencia, es un importante concepto en la orientacin a objetos, y ambos los cultivaremos a lo largo de ste mdulo. Aunque los objetos son creados desde clases, los diagramas de objetos normalmente se muestran muy diferentes a sus diagramas de clases relacionados. La Figura 11, por ejemplo, muestra los objetos actuales que existen en el sistema y por tanto no muestra que esos objetos estn derivados desde cualquier superclase: para esa informacin nos referiremos al diagrama de clases.

Ejemplo 1.3 paso 6. Una Secuencia de Diagrama UML CoincidenteHasta ahora hemos visto un diagrama de clases, que muestra la estructura de clase, y un diagrama de objetos, que proporciona una instantnea del estado. Ambas son representaciones estticas del sistema. Un diagrama de secuencia es una forma del diagrama de objetos que podemos usar para mostrar aspectos dinmicos del programa, tales como el paso de un mensaje o la interaccin entre objetos (Figura 12). Los objetos (no las clases) aparecen en cuadros separados de izquierda a derecha a lo largo de la parte superior de la pgina. En UML, los nombres de los objetos son subrayados y los nombres de clases no. Los objetos pueden ser identificados a travs de su nombre y clase, slo su nombre o slo su clase. Aqu tenemos los mismos objetos que en diagrama de objetos. Tambin tenemos al usuario (llamado actor) que inicia la secuencia picando sobre un RadioButton y por tanto el actor tambin aparece como uno de los objetos, en la parte izquierda del diagrama. El tiempo transcurre desde la parte superior del diagrama hacia abajo. Una lnea discontnua cayendo verticalmente debajo de cada objeto es la lnea de vida del objeto, mostrando el tiempo durante el cual el objeto existe. Una barra superpuesta sobre la lnea de vida muestra la activacin de un objeto o la toma del foco. Para sta secuencia particular (Figura 12), las lneas de vida de ambos objetos se extienden ms all del diagrama y por tanto no mostraremos ninguna creacin o destruccin de objetos. En ste ejemplo, el manejador de evento OnClick del radAuxShow de frmMain enva mensajes a frmAux para mostrarse y ocultarse a s mismo.

Aprendiendo OOP con Delphi

Pgina 18 de 32

Creado el 16/06/09

Figura 12: El diagrama de secuencia para el ejemplo 1.3, pasos 1y 2

El paso de mensajes es un mecanismo bsico de comunicacin y sincronizacin dentro de la OO. Un mensaje es la invocacin del mtodo de un objeto. Un mensaje es mostrado como una flecha desde la activacin de un objeto a otro. Existe una relacin de asociacin entre estos dos objetos: frmMain y frmAux son ambos objetos independientes con lneas de vida separadas, ya que ninguno de ellos ni crea ni libera al otro. Sin embargo, como vimos en el diagrama de objetos, frmMain usa frmAux, y por tanto la asociacin es a veces referida como una relacin UsaUn (UsesA) .

Ejemplo 1.3 paso 7. Creacin y Liberacin ExplcitaCuando iniciamos una nueva aplicacin o aadimos un nuevo formulario a una aplicacin existente, Delphi automticamente, como parte de su capacidad RAD, establece la definicin de clase del formulario (p.ej., lneas 716 en paso 1 (unit MainForm) y lneas 79 en paso 2 (unit AuxForm)), declara una referencia a un objeto de sta clase (p.ej., lneas 1718 en paso 1 y lneas 1011 en paso 2) y entonces construye el objeto (p.ej., lneas 910 en paso 3 (el programa de archivo de proyecto TwoUnits)). As, por la forma en que Delphi (y otros lenguajes) implementa OO, hay tres fases para crear un objeto:

Definir la clase. Declarar una referencia (o instancia) al objeto, y Crear el objeto.

La definicin de clase es un juego de instrucciones para crear objetos, algo como un conjunto de planes de fabricacin. La declaracin del objeto establece un mecanismo para acceder al objeto creando una referencia en la pila. El constructor del objeto usa la definicin de clase para crear un objeto en memoria (la pila).

Aprendiendo OOP con Delphi

Pgina 19 de 32

Creado el 16/06/09

En la actual versin del programa Delphi toma la responsbilidad de realizar todos estos pasos. Dentro de poco definiremos clases y declararemos y crearemos objetos en los programas que escribamos. Como un primer paso en sta direccin, intervendremos en el proceso de autocreacin de objetos RAD y crearemos el formulario auxiliar como parte de un programa, en lugar de permitir a Delphi que lo cree automticamente. Podemos eliminar todos los formularios de un proyecto excepto el formulario principal desde la lista de autocreacin. Si hacemos esto, Delphi no crear automticamente nunca ms esos formularios y el programador deber crearlos explcitamente en el cdigo de programa antes de que puedan ser utilizados (tambin podemos elegir qu formulario ser el formulario principal). Para evitar la sobreescritura de la actual versin de ste cdigo, almacene estas dos units y el archivo de proyecto en un nuevo directorio para ste ejemplo antes de nada. Ahora use la opcin de men Project | Options y seleccione la pestaa Forms. El panel de la izquierda lista los formularios autocreados. Seleccione frmAuxiliary en ste panel y haga click en el botn de flecha derecha para transferirlo desde la lista de autocreados a la de disponibles (Figura 13).

Figura 13: Instruyendo a Delphi para no crear automticamente frmAuxiliary

Seleccione OK para cerrar la ventana de Opciones de Proyecto. Para programar nuestra versin anterior de interfaz de usuario para crear (y liberar) el formulario auxiliar, aada un GroupBox al formulario y luego aada botones Create y Free al GroupBox (figuras 14 y 15).

Figura 14: Creando y liberando un objeto de interfaz de usuario explcitamente

Aprendiendo OOP con Delphi

Pgina 20 de 32

Creado el 16/06/09

Figura 15: Objectos en el formulario principal modificado

Cambie la unit MainForm a lo siguiente:1 unit MainForm; 2 interface 3 uses 4 Windows, Messages, SysUtils, Variants, Classes, Graphics, 5 Controls, Forms, Dialogs, StdCtrls; 6 type 7 TfrmMain = class(TForm) 8 radAuxShow: TRadioButton; 9 radAuxHide: TRadioButton; 10 gpbAuxiliary: TGroupBox; 11 btnCreate: TButton; 12 btnFree: TButton; 13 procedure radAuxShowClick(Sender: TObject); 14 procedure radAuxHideClick(Sender: TObject); 15 procedure btnCreateClick(Sender: TObject); 16 procedure btnFreeClick(Sender: TObject); 17 end; // end TfrmMain = class(TForm) 18 var 19 frmMain: TfrmMain; 20 implementation 21 uses AuxForm; 22 {$R *.dfm} 23 procedure TfrmMain.radAuxShowClick(Sender: TObject); 24 begin 25 try 26 frmAuxiliary.Show; 27 except 28 ShowMessage ('Auxiliary Form does not exist'); 29 radAuxShow.Checked := False; 30 end; 31 end; // end procedure TfrmMain.radAuxShowClick 32 procedure TfrmMain.radAuxHideClick(Sender: TObject); 33 begin 34 try 35 frmAuxiliary.Hide; 36 except 37 ShowMessage ('Auxiliary Form does not exist'); 38 radAuxHide.Checked := False;

Aprendiendo OOP con Delphi

Pgina 21 de 32

Creado el 16/06/09

39 end; 40 end; // end procedure TfrmMain.radAuxHideClick 41 procedure TfrmMain.btnCreateClick(Sender: TObject); 42 begin 43 if frmAuxiliary = nil then 44 frmAuxiliary := TfrmAuxiliary.Create(Self) 45 else 46 ShowMessage ('Auxiliary Form already exists'); 47 end; // end procedure TfrmMain.btnCreateClick 48 procedure TfrmMain.btnFreeClick(Sender: TObject); 49 begin 50 try 51 frmAuxiliary.Hide; 52 frmAuxiliary.Free; 53 frmAuxiliary := nil; 54 except 55 ShowMessage ('Auxiliary Form does not exist'); 56 end; 57 end; // end procedure TfrmMain.btnFreeClick 58 end. // end unit MainForm

Los cambios requeridos pueden ser ms extensivos de lo esperado. Ya que en cualquier momento frmAuxiliary puede o no existir, en cada momento necesitamos comprobar la existencia de frmAuxiliary antes de intentar realizar cualquier operacin sobre l (en la anterior versi autocreadora vimos que frmAuxiliary siempre exista y por tanto en ese caso no son necesarias estas comprobaciones). Hemos aadido un manejador de evento OnClick para cada uno de los dos nuevos botones. De los cuatro manejadores de evento que tenemos ahora, tres usan manejo de excepciones para controlar situaciones en las que pudiramos realizar una operacin sobre un objeto no existente. Si intentamos mostrar un no existente frmAuxiliary, la lnea 26 lanza una excepcin que es capturada por las lneas 28 y 29. Similarmente, si intentamos ocultar un form no existente, la lnea 35 lanza una excepcin que es capturada por las lneas 37 y 38. Si intentamos liberar un formulario no existente (lnea 51) la lnea 55 se encargar del manejo de la requerida excepcin. El manejo de excepciones no controlar el intento de crear otro frmAuxiliary cuando uno previo ya existe, as que usaremos una aproximacin diferente cuando instanciemos frmAuxiliary. La lnea 43 comprueba si el nombre frmAuxiliary se refiere a un objeto vlido. Si no lo es, la lnea 44 lo crea. Si lo es, la lnea 46 lanza un mensaje al usuario y no hay intento de instanciar un segundo objeto TfrmAuxiliary. Usaremos ste ejemplo para ver con ms profundidad el ciclo de vida de un objeto y la forma en que ste puede ser referenciado por otros objetos. La lnea 21 es una clusula uses local indicando que sta unit tiene acceso a las secciones pblicas de AuxForm. La unit Auxform declara una variable pblica (p.ej., una referencia a un objeto) frmAuxiliary de tipo TfrmAuxiliary (paso 2, lneas 10 y 11). Esa referencia frmAuxiliary es visible para la unit MainForm. Si una referencia a un objeto tiene el valor nil no se est refiriendo actualmente a ningn objeto: cualquier otro valor es una referencia a un objeto. Cuando el usuario pulsa btnCreate, su manejador de evento OnClick se ejecuta. ste primero comprueba si la referencia frmAuxiliary se refiere a un objeto vlido (lnea 43 anterior). Si no, pasa a la lnea 44:frmAuxiliary := TfrmAuxiliary.Create(Self)

Esto invoca al mtodo Create de TfrmAuxiliary, envindole el valor Self. TfrmAuxiliary es declarado pblicamente en la unit AuxForm, y la unit MainForm tiene acceso a AuxForm a travs de su clusula local uses (lnea 21 anterior). TfrmAuxiliary est derivado desde TForm (paso 2, lnea 7). TForm tiene un mtodo llamado Create, y por tanto TfrmAuxiliary hereda Create desde TForm: un ejemplo de cmo la herencia facilita la reutilizacin. Create es un tipo especial de mtodo, llamado Constructor.

Aprendiendo OOP con Delphi

Pgina 22 de 32

Creado el 16/06/09

Un constructor crea un objeto desde la plantilla proporcionada en una definicin de clase. Para clases VCL, ste constructor requiere un propietario del objeto como parmetro de entrada. Aqu damos a Self (p.ej., frmMain) como el propietario. El constructor retorna una referencia al nuevo objeto creado. En la lnea 44 ste valor de retorno es asignado a frmAuxiliary. Retornando al estamento If en la lnea 43, si frmAuxiliary se refiere a un objeto vlido, la lnea 46 enva un mensaje indicando que el objeto ya existe y que no se hace intento alguno de crear otra instancia de ste objeto. Ahora que existe, frmAuxiliary puede ser mostrado y ocultado tantas veces como se requiera por los dos manejadores de evento del RadioButton.frmAuxiliary existe, ste estamento frmAuxiliary. Free es un mtodo tipo

Cuando llega el momento de destruir frmAuxiliary, la lnea 51 pimero lo oculta (Hide). Si ser exitoso y la lnea 52 invocar entonces al mtodo Free de Destructor que TfrmAuxiliary ha heredado desde TForm.

Tras liberar frmAuxiliary, ste ya no existe y por tanto debemos establecer su referencia a nil (lnea 53). Tras esto, el manejador de evento OnClick de btnFree termina. La otra posibilidad es que frmAuxiliary no exista cuando se ejecuta la lnea 51. El intento de referirse a l entonces lanza una excepcin y la ejecucin contina en la seccin Except del constructor TryExceptEnd (p.ej., en la lnea 55). Esto genera un mensaje apropiado sin ningn intento de liberar el objeto no existente. Ejecute y pruebe el programa. El el IDE de Delphi el lanzamiento de una excepcin puede provocar una rotura en el depurador en el punto en que la excepcin es lanzada. Para continuar cuando esto pase, presione para continuar o o para ir un paso ms o para continuar paso a paso, respectivamente. Para activar o desactivar la rotura en el depurador cuando ocurre una excepcin, utilice Tools | Debugger Options en Delphi 6/7 o Tools | Options en Delphi 8. En vez de usar manejo de excepciones, podramos haber codificado la secuencia de liberacin del objeto en un estamento If como sigue:procedure TfrmMain.btnFreeClick(Sender: TObject); begin if frmAuxiliary = nil then ShowMessage ('Auxiliary Form does not exist') else begin frmAuxiliary.Hide; frmAuxiliary.Free; frmAuxiliary := nil; end; end; // end procedure TfrmMain.btnFreeClick

En sta variacin nos aseguramos de que frmAuxiliary actualmente no existe antes e que intentemos una operacin sobre l (p.ej., ocultarlo). Es frecuentemente posible usar tanto manejo de excepciones como estamentos If para prevenir intentos de operaciones sobre objetos invlidos, y cada aproximacin tiene sus ventajas y desventajas. En ste mdulo generalmente usaremos la aproximacin del manejo de excepciones. Esto nos da una breve introduccin a los procesos de creacin y liberacin de un objeto. Retornaremos a estos procesos con ms detalle en un prximo captulo.

Ejemplo 1.3 paso 8: Tiempos de Vida en un Diagrama de SecuenciaEn el paso 7 especficamente creamos un objeto cuando lo necesitamos y lo liberamos cuando terminamos con l, y as tenemos control completo de su tiempo de vida. Podemos mostrar explcitamente el tiempo de vida de un objeto en un diagrama de secuencia (Figura 16). El mensaje a la propiedad Name del objeto representa al constructor y una cruz sobre su lnea de vida muestra su destruccin.

Aprendiendo OOP con Delphi

Pgina 23 de 32

Creado el 16/06/09

Ejemplo 1.3. SumarioHay un nmero de etapas para crear un objeto. Primero creamos una definicin de clase. Una clase noes todava un objeto y no tiene datos propios. No podemos usarla directamente ya que slo es una plantilla. As que declaramos uno o ms nombres para actuar como referencias a objetos y entonces instanciamos los objetos desde la definicin de clase. Aunque cada objeto es construdo en base a la misma plantilla, la definicin de clase, un objeto instanciado es una entidad independiente con vida propia. Por ejemplo, cada formulario tiene su propia position y caption, y podemos reposicionar y redimensionar cada uno de forma independiente sin que afecte a los dems. En UML, un diagrama de clase muestra la estructura esttica de las clases en el programa. Un diagrama de objeto proporciona una instantnea de los objetos instanciados en un momento determinado en el programa. Un diagrama de secuencia muestra comportamiento dinmico entre varios objetos. Hemos investigado en torno a tiempos de vida de objetos, crendolos y liberndolos segn necesitemos en vez de crearlos cuando el programa inicia y liberndolos cuando el programa termina. Asumimos la responsabilidad de liberar el objeto estableciendo el propietario a nil en la llamada al mtodo Create. Cuando liberamos un objeto tambin debemos establecer su referencia a nil. Hacemos esto bien llamando al mtodo Free y luego estableciendo la referencia a nil, o bien (como veremos en un futuro ejemplo) usando el procedimiento FreeAndNil. Cuando lo necesitemos, podemos mostrar el inicio y fin de la lnea de tiempo de vida de un objeto en un diagrama de secuencia. Un mensaje al Name del objeto indica su construccin. Una cruz sobre su lnea de vida muestra su destruccin. Hay varios tipos diferentes de mensajes y distinguiremos entre ellos a travs de diferentes notaciones.

Aprendiendo OOP con Delphi

Pgina 24 de 32

Creado el 16/06/09

Figura 16: Mostrando la creacin y destruccin de objeto en un diagrama de secuencia

Ejemplo 1.4. Definiendo un Formulario Directamente en el CdigoEn el ejemplo anterior, usamos la caracterstica RAD de Delphi para definir la clase TfrmAuxiliary. Entonces lo instanciamos y liberamos desde cdigo de programa. Como alternativa, en ste ejemplo definiremos directamente TfrmAuxiliary desde TForm usando cdigo de programa y luego instancindolo.

Ejemplo 1.4 paso 1: Modificando el Programa AnteriorDentro de una filosofa de reutilizacin, y para enfatizar los cambios que haremos en ste ejemplo, abra el proyecto del ejemplo anterior y almacnelo en un nuevo directorio. Modificaremos sta copia. Ya que definimos el formulario auxiliar directamente desde TForm (lnea 48 debajo) no necesitamos la unit AuxForm del ejemplo anterior. As en la unit MainForm elimine el estamento uses AuxForm. Ahora necesitamos eliminar AuxForm del proyecto. Use la secuencia de men Project | Remove from Project, selecciona la unit AuxForm y haga click en OK (Para mantener su directorio en tamao ptimo, ahora debera eliminar la unit AuxForm del directorio que est usando para ste ejemplo). La unit AuxForm declaraba una referencia a frmAuxiliary. Esta unit ya no es ms parte del proyecto y por tanto declaramos sta referencia como un campo de datos privado en la declaracin de tipos de TfrmMain (lneas 1718 debajo). La referencia frmAuxiliary ahora es un campo de datos privado en TfrmMain.

Aprendiendo OOP con Delphi

Pgina 25 de 32

Creado el 16/06/09

Como en el ejemplo anterior, si el objeto al que se refiere frmAuxiliary no existe an (lnea 46) lo creamos, pero sta vez lo creamos directamente desde la librera de clases de TForm (lnea 48) (En el anterior ejemplo lo creamos desde TfrmAuxiliary: ejemplo 1.3, paso 4, lnea 44). Ahora lo inicializamos en cdigo de programa (lneas 4951) ya que ya no tenemos acceso al Inspector de Objetos para inicializar frmAuxiliary. Tambin establecemos los valores de Left y Top para frmAuxiliary (lneas 5253) ya que no tenemos un apropiado manejador de eventos OnShow (refirase al ejemplo 1.3, paso 2, lneas 1822). El mostrar, ocultar y liberar frmAuxiliary permanece igual que antes.1 unit MainForm; 2 interface 3 uses 4 Windows, Messages, SysUtils, Variants, Classes, Graphics, 5 Controls, Forms, Dialogs, StdCtrls; 6 type 7 TfrmMain = class(TForm) 8 radAuxShow: TRadioButton; 9 radAuxHide: TRadioButton; 10 gpbAuxiliary: TgroupBox; 11 btnCreate: TButton; 12 btnFree: TButton; 13 procedure radAuxShowClick(Sender: TObject); 14 procedure radAuxHideClick(Sender: TObject); 15 procedure btnCreateClick(Sender: TObject); 16 procedure btnFreeClick(Sender: TObject); 17 private 18 frmAuxiliary: TForm; // Composition 19 end; // end TfrmMain = class(TForm) 20 var 21 frmMain: TfrmMain; 22 implementation 23 {$R *.dfm} 24 procedure TfrmMain.radAuxShowClick(Sender: TObject); 25 begin 26 try 27 frmAuxiliary.Show; 28 except 29 ShowMessage ('Auxiliary Form does not exist'); 30 radAuxShow.Checked := False; 31 radAuxHide.Checked := False; 32 end; 33 end; // end procedure TfrmMain.radAuxShowClick 34 procedure TfrmMain.radAuxHideClick(Sender: TObject); 35 begin 36 try 37 frmAuxiliary.Hide; 38 except 39 ShowMessage ('Auxiliary Form does not exist'); 40 radAuxHide.Checked := False; 41 radAuxShow.Checked := False; 42 end; 43 end; // end procedure TfrmMain.radAuxHideClick 44 procedure TfrmMain.btnCreateClick(Sender: TObject); 45 begin 46 if frmAuxiliary = nil then

Aprendiendo OOP con Delphi

Pgina 26 de 32

Creado el 16/06/09

47 begin 48 frmAuxiliary := TForm.Create(Self); 49 frmAuxiliary.Caption := 'frmAuxiliary'; 50 frmAuxiliary.Height := 150; 51 frmAuxiliary.Width := 180; 52 frmAuxiliary.Left := Random (600); // not part of OnShow 53 frmAuxiliary.Top := Random (400); 54 end 55 else 56 ShowMessage ('Auxiliary Form already exists'); 57 end; // end procedure TfrmMain.btnCreateClick 58 procedure TfrmMain.btnFreeClick(Sender: TObject); 59 begin 60 try 61 frmAuxiliary.Hide; 62 frmAuxiliary.Free; 63 frmAuxiliary := nil; 64 except 65 ShowMessage ('Auxiliary Form does not exist'); 66 end; 67 end; // end procedure TfrmMain.btnFreeClick 68 initialization 69 Randomize; 70 end. // end unit MainForm

Cuando ejecuta ste programa aparece igual que en el ejemplo anterior. Entonces, Cul es el sentido de los cambios que hemos hecho? Declaramos frmAuxiliary (de clase TForm) como integrante de la clase TfrmMain declarndolo como miembro de sus datos privados (como campo de datos) (lnea 18). Entonces lo creamos (lnea 48), lo manipulamos (lneas 4953) y, cuando hemos terminado con l, lo liberamos (lnea 62). Esta relacin privada crear-usar-liberar entre un objeto y otro es un ejemplo de composicin. Esto es similar a la asociacin, pero mientras que la asociacin es una relacin entre dos objetos independientes, con la composicin un objeto crea, usa y destruye un objeto privado filial. La composicin es un importante concepto en OO y retornaremos a ella varias veces en el prximo captulo.

Ejemplo 1.4 paso 2: Mtodos y Enlazado de Manejadores de EventoEn el paso 1 anterior vimos que cuando creamos un formulario dinmicamente en cdigo tenemos acceso a todas sus propiedades (las pblicas). Pero Qu pasa con sus eventos? Podemos crearlos y acceder a ellos tambin? Podemos, como muestra el siguiente cdigo. En el ejemplo anterior usamos el manejador de eventos OnShow del formulario auxiliar para asignar valores aleatorios a las propiedades Left y Top de forma que el subformulario aparece en diferentes posiciones cada vez que es mostrado. Cambiaremos el programa del paso anterior para tener un manejador de eventos OnShow similar. Cmo creamos un manejador de eventos? Veamos cmo lo hace Delphi y luego intentaremos algo similar. Cuando Delphi crea un manejador de eventos, ste declara dicho manejador en la definicin de clase (p.ej., ejemplo 1.3, paso 2, lnea 8). En la lnea 19 siguiente copiamos ste formato. Las secciones private y public de la definicin de clase son para uso del programador y colocamos la declaracin del manejador de eventos en la seccin private (lnea 11) ya que es la nica unit que necesita acceder a l. Podemos dar al manejador el nombre que queramos, y lo llamaremos frmAuxiliaryShow.

Aprendiendo OOP con Delphi

Pgina 27 de 32

Creado el 16/06/09

En desarrollo RAD, el enlace entre un evento y su manejador es controlado a travs del Inspector de Objetos. No lo podemos usar aqu ya que nosotros enlazamos el evento OnClick al manejador de eventos frmAuxShow mediante cdigo de programa (p.ej., lnea 53). Al igual que Width es una propiedad a la cual podemos asignar un nombre tanto constante como variable (p.ej., lnea 24), OnShow es una propiedad es una propiedad a la cual podemos asignar el nombre de un mtodo apropiado (As como tenemos que usar tipos apropiados cuando asignamos variables y no podemos, por ejemplo, asignar un string a un integer, cuando asignamos mtodos ellos deben tener una firma de mtodo coincidente. Es por ello que definimos frmAuxShow con un parmetro Sender de tipo TObject aunque no vaya a ser usado por el mtodo (lnea 19)). Finalmente implementamos el cuerpo del manejador de eventos com hicimos anteriormente (ejemplo 1.3, paso 2, lneas 1822). ste se ejecutar cuando el formulario auxiliar sea mostrado en la pantalla a consecuencia de la asignacin en la lnea 25. En resumen, tenemos un mtodo privado (lnea 19 siguiente) que es usado como manejador de evento, p.ej., iniciado por un evento, y por tanto sigue el mismo formato que los manejadores de evento generados por Delphi. Como un nombre de evento (p.ej., OnShow) es una propiedad, podemos enlazar el manejador de eventos al evento para el objeto que creamos (p.ej., lnea 53). Esto nos proporciona el mismo efecto que enlazando un manejador de eventos a travs del Inspector de Objetos. Los mtodos adicionales que creamos para el formulario filial no necesitan ser manejadores de eventos. Pueden ser mtodos de ayuda o de acceso a los que podemos llamar a travs de cdigo de programa. Crearemos un mtodo de ayuda FormRefFail para usarlo cuando intentemos una referencia invlida a frmAuxiliary. Primero, declaramos el mtodo de forma privada (lnea 20) ya que ninguna otra unit debera tener acceso a l. ste es un procedimiento, ya que no retorna ningn valor (veremos mtodos de acceso en prximos ejemplos). Ejecute ste programa. Desde una perspectiva externa, funciona igual que antes.1 unit MainForm; 2 interface 3 uses 4 Windows, Messages, SysUtils, Variants, Classes, Graphics, 5 Controls, Forms, Dialogs, StdCtrls; 6 type 7 TfrmMain = class(TForm) 8 radAuxShow: TRadioButton; 9 radAuxHide: TRadioButton; 10 gpbAuxiliary: TGroupBox; 11 btnCreate: TButton; 12 btnFree: TButton; 13 procedure radAuxShowClick(Sender: TObject); 14 procedure radAuxHideClick(Sender: TObject); 15 procedure btnCreateClick(Sender: TObject); 16 procedure btnFreeClick(Sender: TObject); 17 private 18 frmAuxiliary: TForm; // Link: composition 19 procedure frmAuxiliaryShow(Sender: TObject); // event handler 20 procedure FormRefFail; // helper method 21 end; // end TfrmMain = class(TForm) 22 var 23 frmMain: TfrmMain; 24 implementation

Aprendiendo OOP con Delphi

Pgina 28 de 32

Creado el 16/06/09

25 {$R *.dfm} 26 const // unit level constant 27 Mssgs: Array [0..1] of string = ('Auxiliary Form does not exist', 28 'Auxiliary Form already exists'); 29 procedure TfrmMain.radAuxShowClick(Sender: TObject); 30 begin 31 try 32 frmAuxiliary.Show; 33 except 34 FormRefFail; 35 end; 36 end; // end procedure TfrmMain.radAuxShowClick 37 procedure TfrmMain.radAuxHideClick(Sender: TObject); 38 begin 39 try 40 frmAuxiliary.Hide; 41 except 42 FormRefFail; 43 end; 44 end; // end procedure TfrmMain.radAuxHideClick 45 procedure TfrmMain.btnCreateClick(Sender: TObject); 46 begin 47 if frmAuxiliary = nil then 48 begin // setting frmAuxiliarys properties 49 frmAuxiliary := TForm.Create(Self); 50 frmAuxiliary.Caption := 'frmAuxiliary'; 51 frmAuxiliary.Height := 150; 52 frmAuxiliary.Width := 180; 53 frmAuxiliary.OnShow := frmAuxiliaryShow; // ref to event handler 54 end 55 else 56 ShowMessage (Mssgs [1]); 57 end; // end procedure TfrmMain.btnCreateClick 58 procedure TfrmMain.btnFreeClick(Sender: TObject); 59 begin 60 try 61 frmAuxiliary.Hide; 62 frmAuxiliary.Free; 63 frmAuxiliary := nil; 64 except 65 FormRefFail; 66 end; 67 end; // end procedure TfrmMain.btnFreeClick 68 procedure TfrmMain.frmAuxiliaryShow(Sender: TObject); 69 begin 70 frmAuxiliary.Left := Random (600); 71 frmAuxiliary.Top := Random (400); 72 end; // end procedure TfrmAuxiliary.FormShow 73 procedure TfrmMain.FormRefFail; 74 begin 75 ShowMessage (Mssgs [0]); 76 radAuxHide.Checked := False; 77 radAuxShow.Checked := False; 78 end; // end procedure TfrmMain.FormRefFail 79 initialization

Aprendiendo OOP con Delphi

Pgina 29 de 32

Creado el 16/06/09

80 Randomize; 81 end. // end unit MainForm

Ejemplo 1.4 paso 3: Diagramas UML CoincidentesCmo podemos representar la situacin anterior en un diagrama de clases? Dos tipos de relaciones existen entre TfrmMain y TForm. Primero, TfrmMain est derivado desde TForm (lnea 7). Segundo, existe una relacin de composicin entre los dos, ya que TfrmMain contiene un objeto privado de tipo TForm (lnea 18) que ste define, crea, usa y destruye. Podemos mostrar estas dos conexiones entre TfrmMain y TForm en el diagrama de clases (Figura 17). (Recuerde que la herencia es mostrada por una punta de flecha cerrada pero hueca y la composicin con un diamante relleno prximo a la clase compuesta).Figura 17: Una subclase conteniendo una instancia de su

superclase

Advierta que ste diagrama muestra una relacin entre clases, y no entre objetos. Muestra cmo son las relaciones entre dos clases: tenemos una clase derivada, TfrmMain, desde TForm y TfrmMain transporta, como un campo de datos privado, una referencia a un objeto (independiente) de tipo TForm. No mostramos sta referencia en el diagrama porque est declarada implcitamente por el smbolo del diamante slido y el enlace a TForm. Tanto el manejador de evento enlazado por el programador como el mtodo de ayuda son privados, por lo que sus nombres son precedidos por un smdolo menos. El resto de operaciones (y atributos) son pblicos y por ello van precedidos por un smbolo ms. Y qu hay de un diagrama de objetos? Tras hacer click en btnCreate en el form principal, el diagrama de objetos es (Figura 18):

Figura 18: diagrama de objetos tras hacer click en btnCreate

Tras pulsar el botn btnFree en el formulario principal, el diagrama de objetos es (Figura 19): El diagrama de secuencia para sta versin del programa permanece igual que el anterior (Figura 16).

Aprendiendo OOP con Delphi

Pgina 30 de 32

Creado el 16/06/09

Figura 19: Diagrama de Objeto tras pulsar btnFree

Resumen del CaptuloEn ste captulo hemos visto brevemente:

La unit de Delphi y la estructura de un proyecto Generacin RAD de objetos visuales en Delphi El proceso de definir una clase, declarar una referencia a un objeto de esa clase, instanciar un objeto de esa clase, usar la clase y finalmente liberarla y cmo realizar esto mediante cdigo de programa La herencia (IsA), Asociacin (UsesA) y la Composicin (UsesA) en relaciones OO Interaccin entre objetos: paso simple de mensaje, asociacin y composicin y Representaciones grficas UML:

Un diagrama de clase muestra herencia esttica y estructuras de asociaciones Un diagrama de objetos da instantneas de objetos y sus relaciones en un momento determinado de la ejecucin, y Un diagrama de secuencia muestra la secuencia del paso de mensajes entre objetos.

Este captulo tambin ha introducido:

Las bases de la Orientacin a Objetos y Los manejadores de Evento

Puntos principales: 1. Comprensin del cdigo generado va RAD: clases y objetos. 2. Generacin de objetos visuales a travs de cdigo de programa como precursos de objetos no visuales. 3. Herencia, asociacin y composicin. 4. Diagramas UML de clases, objetos y secuencias. Objetos como entidades independientes: Definiendo y usando una clase. Objetos como entidades derivadas: Herencia simple y composicin. Objetos como entidades que interactan: Asociacin y paso simple de mensaje. Diagramas UML: diagramas de clases, de objetos y de secuencias

Aprendiendo OOP con Delphi

Pgina 31 de 32

Creado el 16/06/09

ProblemasProblema 1.1. Estudio de Captulo 1Identifique en el captulo los ejemplos o secciones apropiados para ilustrar cada comentario hecho en el resumen del captulo.

Problema 1.2. Reemplazo de manejo de excepciones con estamentos IfReemplace todos los estamentos de manejo de execpciones del ejemplo 1.3 con estamentos If.

Problema 1.3. Interfaz CambiadaLa interfaz de usuario para el ejemplo 1.3 paso 7 mezcla botones y RadioBotones, llevndonos a una confusa interfaz de usuario y cdigo repetitivo. Recodifique ste programa, reemplazando los botones con un simple RadioGroup (figuras 20 y 21). Utilice manejo de excepciones en lugar de estamentos If para responder a errores en referencias a objetos.

Figura 20: Una interfaz de usuario demostrando la creacin, uso y destruccin de objetos Figura 21: Componentes que componen la interfaz de usuario

Problema 1.4. Autocreacin y creacin y liberacin controlada va programaEn el ejemplo 1.3 paso 7 eliminamos frmAuxiliary desde la lista de autocreacin y lo creamos y liberamos entonces desde programa. Qu pasa si dejamos frmAuxiliary en la lista de autocreacin pero seguimos utilizando el programa revisado dado en el ejemplo1.3 paso 7?

Problema 1.5. Creando objetos explcitamenteSi ha codificado el problema 1.4 con xito, utilcelo como punto de inicio para ste problema. Modifquelo para definir el formulario auxiliar en cdigo de forma similar al del ejemplo 1.4. Si no ha codificado el problema 1.4 con xito, utilice el ejemplo 1.4 como punto de inicio. 1. En el formulario auxiliar defina dos botones, btnBlue y btnGreen, mediante cdigo (sin usar lascapacidades RAD). D a cada uno un manejador de eventos OnClick para cambiar el color del formulario auxiliar entre MoneyGreen y SkyBlue. 2. Dibuje los correspondientes diagramas UML, mostrando la composicin explcitamente.

Aprendiendo OOP con Delphi

Pgina 32 de 32