0% encontró este documento útil (0 votos)
117 vistas28 páginas

Delphi OOP-Cap 03

Este documento describe los conceptos básicos de las clases y objetos definidos por el programador en Delphi. Introduce un ejemplo de una aplicación para contar elementos que pasan por una cinta transportadora, y describe tres pasos para implementarla: 1) Usando una variable global, 2) Combinando la interfaz de usuario y la lógica de aplicación en un solo objeto, y 3) Separando la interfaz de usuario de la lógica de aplicación en objetos distintos. El objetivo final es ilustrar cómo crear objetos de aplicación definidos por el programador y separ

Cargado por

Adolfo Pachón
Derechos de autor
© Attribution Non-Commercial (BY-NC)
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como ODT, PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
117 vistas28 páginas

Delphi OOP-Cap 03

Este documento describe los conceptos básicos de las clases y objetos definidos por el programador en Delphi. Introduce un ejemplo de una aplicación para contar elementos que pasan por una cinta transportadora, y describe tres pasos para implementarla: 1) Usando una variable global, 2) Combinando la interfaz de usuario y la lógica de aplicación en un solo objeto, y 3) Separando la interfaz de usuario de la lógica de aplicación en objetos distintos. El objetivo final es ilustrar cómo crear objetos de aplicación definidos por el programador y separ

Cargado por

Adolfo Pachón
Derechos de autor
© Attribution Non-Commercial (BY-NC)
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como ODT, PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 28

Creado el 16/06/09

3 Clases y
Objetos definidos por el Programador

Conceptos Principales:

Manteniendo separados la interfaz de usuario y los objetos de la aplicacin: separacin de capacidades (SoC) Imitacin de objetos de interfaz de usuario RAD en clases de aplicacin definidas por el programador Pasos a seguir para el uso de un objeto definido por el programador:

Definir la clase, localizar un nombre (referencia), instanciar el objeto, asignarlo al nombre.

Herencia: derivando una nueva clase desde una existente Empaquetando una clase en una unit El Explorador de Cdigo y el Navegador de Proyecto Disposicin de objetos en memoria

Aprendiendo OOP con Delphi

Pgina 1 de 28

Creado el 16/06/09

Introduccin
Una forma de hacer un programa de ordenador ms robusto y ms susceptible a cambios es construirlo en capas. Uno podra tener una capa de interfaz que se ocupe de la interaccin entre el usuario y el programa, una capa de aplicacin que implemente las operaciones requeridas por la aplicacin, y una capa de persistencia que se ocupe del almacenamiento permanente de los datos. Este enfoque es a veces llamado el Modelo de las Tres Capas y es una implementacin de un principio llamado Principio de Separacin de Capacidades. El generador GUI de Delphi gestiona la capa de interfaz de usuario muy efectivamente. Pero Qu pasa con la capa de aplicacin? Para empezar nos fijaremos en la definicin e instanciacin de nuestras propias clases para proporcionar lgica de aplicacin. Mientras que es posible aadir lgica de aplicacin a los objetos de interfaz de usuarios generados mediante RAD, es una buena prctica de programacin en su lugar separar la interfaz de usuario de la de aplicacin, y es desde sta perspectiva desde la cual desarrollaremos nuestras propias clases.

Creando una simple Clase No-Visual


Cuando creamos un nuevo formulario en Delphi, nosotros reutilizamos un nmero existente de clases existentes, tales como TForm, TButton y TLabel, y las combinamos para crear una nica, nueva clase de interfaz visual de usuario. Nuestros programas anteriores consisten en simples objetos formulario y toda la operatoria del programa ocurre dentro de estos objetos contenidos en s mismos. Sin embargo, un programa orientado a objetos es un sistema de objetos cooperantes, y pronto nos moveremos a programas con varios objetos formulario. Cada uno de estos tiene un objeto de interfaz de usuario separado que comunica y coopera con otros objetos de interfaz de usuario existentes en el programa. Pero un programa realista no consiste slo en objetos de interfaz de usuario. Tambin contiene objetos aplicacin y estos son el foco para ste captulo. Los objetos de aplicacin son generados por el programador, ya que el uso de soporte RAD para la generacin de objetos de interfaz de usuario no es posible para el desarrollo de objetos aplicacin. Para establecer un contexto para programar un objeto aplicacin, usaremos el ejemplo de una cinta transportadora que mueve los elementos en un depsito de almacenamiento a una zona de envo. Para mantener un registro del nmero de artculos, un botn Aadir Elemento es pulsado cada vez que pasa por la cinta transportadora. Un supervisor controla el nmero total de elementos pulsando y manteniendo presionado un botn Display. Cuando el botn es liberado, la pantalla se borra. Al final de cada turno, el total es restablecido a cero.

Aprendiendo OOP con Delphi

Pgina 2 de 28

Creado el 16/06/09

Figura 2: Componentes en la interfaz de Figura 1: Interfaz de usuario para contar elementos usuario

La interfaz de usuario aparece en la Figura 1 y el Object Tree View, el cual est disponible en Delphi 6 y 7 y que muestra los componentes en el formulario, aparece en la Figura 2 (Delphi 8 tiene el Model View, el cual es ms sofisticado). Vamos a desarrollar el programa por etapas para ayudar a aclarar algunas de las importantes caractersticas de programacin OO. En primer lugar vamos a crear un programa no-OO, donde usamos una simple variable para mantener un registro del nmero de artculos. Luego haremos la parte de conteo de elementos del formulario, lo que nos llevar a un objeto combinado interfaz/aplicacin. Finalmente, crearemos un objeto aplicacin separado del objeto de interfaz de usuario.

Ejemplo 3.1. Un programa no-OO


Inicie una nueva aplicacin. Sobre el Object TreeView (Figura 2) aada componentes al formulario desde la paleta Component / Tool, en Delphi 4 a 7, usando la secuencia de men View | Component List. Para hacer nuestros programas ms legibles usaremos un prefijo de tres letras para cada tipo de componente, tal como se lista en el Apndice 1. As, un formulario ser llamado frm..., un botn btn..., una etiqueta lbl... y as con el resto.

Ejemplo 3.1 - paso 1: Usando una variable Global


1. Nuestra primera versin utiliza un integer declarado en la seccin de implementacin de la unit para registrar el nmero de elementos (lneas 2627 a continuacin). Como parte de la declaracin de tipo del formulario tenemos un dato privado llamado Count que ha sido comentado mediante llaves (lnea 20). usaremos esto como una alternativa en el siguiente paso. El botn btnAddItem tiene un manejador de eventos OnClick (lneas 14, 2831), el botn btnDisplay tiene los manejadores de evento OnMouseDown (lneas 1516, 3236) y OnMouseUp (lneas 1718, 3741) y el BitBtn bmbReset tiene un evento OnClick (lneas 13, 4245):
1 unit GlobalU; 2 interface 3 uses 4 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, 5 Forms, Dialogs, StdCtrls, Buttons; 6 type 7 TfrmCount = class(TForm)

Aprendiendo OOP con Delphi

Pgina 3 de 28

Creado el 16/06/09

8 gpbItems: TGroupBox; 9 lblTotal: TLabel; 10 bmbReset: TBitBtn; 11 btnAddItem: TButton; 12 btnDisplay: TButton; 13 procedure bmbResetClick(Sender: TObject); 14 procedure btnAddItemClick(Sender: TObject); 15 procedure btnDisplayMouseDown(Sender: TObject; 16 Button: TMouseButton; Shift: TShiftState; X, Y: Integer); 17 procedure btnDisplayMouseUp(Sender: TObject; 18 Button: TMouseButton; Shift: TShiftState; X, Y: Integer); 19 private 20 {Count: integer; // for step 2} 21 end; // end TfrmCount = class(TForm) 22 var 23 frmCount: TfrmCount; 24 implementation 25 {$R *.dfm} 26 var 27 Count: integer = 0; 28 procedure TfrmCount.btnAddItemClick(Sender: TObject); 29 begin 30 Inc (Count); 31 end; // end procedure TfrmCount.btnAddItemClick 32 procedure TfrmCount.btnDisplayMouseDown(Sender: TObject; 33 Button: TMouseButton; Shift: TShiftState; X, Y: Integer); 34 begin 35 lblTotal.Caption := IntToStr (Count); 36 end; // end procedure TfrmCount.btnDisplayMouseDown 37 procedure TfrmCount.btnDisplayMouseUp(Sender: TObject; 38 Button: TMouseButton; Shift: TShiftState; X, Y: Integer); 39 begin 40 lblTotal.Caption := ''; 41 end; // end procedure TfrmCount.btnDisplayMouseUp 42 procedure TfrmCount.bmbResetClick(Sender: TObject); 43 begin 44 Count := 0; 45 end; // end procedure TfrmCount.bmbResetClick 46 end. // end unit GlobalU

Este es un simple programa que funciona. Sin embargo, tiene un problema potencial. Debido a que existen tres procedimientos distintos, y los manejadores de eventos btnItemsClick, btnDisplayMouseDown y bmbResetClick se refieren todos al valor de Count, Count debe ser una variable a nivel de unidad (lneas 2627). El hecho de dar a las variables mbito de nivel de unidad no es generalmente una buena idea, y normalmente es mejor evitar hacerlo1. As que en el prximo paso haremos a sta variable parte del objeto de interfaz de usuario. Antes de pasar al siguiente paso, advierta que usamos la expresin Inc(Count) y no Count:=Count+1 en la lnea 30. Aunque funcionan ambas, Inc(Count) genera cdigo ms optimizado y es algo ms rpido y especialmente til en bucles.
1 En Delphi una variable de nivel de unidad es efectivamente una variable de clase. Si varios objetos son creados desde una clase con una variable de nivel de unidad, la misma variable de nivel de unidad est disponible para todos los objetos. Cada objeto comparte la variable de nivel de unidad: ninguno de los objetos individuales tienen su popia variable.

Aprendiendo OOP con Delphi

Pgina 4 de 28

Creado el 16/06/09

Ejempo 3.1 paso 2: Un Objeto Combinado Interfaz Usuario/Aplicacin


Para eliminar la variable de nivel de unidad del paso 1, comente la declaracin de nivel de unidad (lneas 2627 anteriores) y descomente el campo de datos privado del formulario (lnea 20). Todas las referencias a Count en los manejadores de eventos se referirn ahora a un campo de datos privado del formulario y no a una variable de nivel de unidad. Ejecute el programa y testelo. Para el usuario el programa funciona como el anterior, pero en lugar de una variable de nivel de unidad el programa ahora usa un campo de datos privado del objeto. Este cambio representa una mejora, pero todava tenemos un problema. Ahora hemos modificado la clase de interfaz de usuario del RAD para incluir datos de aplicacin. As que la interfaz de usuario debe saber cmo incrementar el contador (lnea 30), cmo acceder a l (lnea 35) y cmo resetearlo (lnea 44): la interfaz del usuario debe tener conocimiento de los detalles sobre cmo funciona la aplicacin. El principio de separacin de capacidades significa que una interfaz de usuario no tendra por qu saber cmo funciona la aplicacin, slo necesita saber cmo comunicar con objetos de aplicacin en respuesta a entradas del usuario. Este cambio es un paso en la direccin adecuada , pero la mezcla de la interfaz de usuario y la aplicacin harn la reutilizacin o futuros cambios ms difcil (p.ej., si por alguna razn desconocida Count en la lnea 20 es cambiada a un double en lugar de un integer, las lneas 30 y 35 causarn errores de compilacin). Sera mejor encapsular los datos de las aplicaciones y las operaciones llevadas a cabo por separado, fuera de la interfaz de usuario. Como breve inciso en el estilo de programacin, nosotros explcitamente inicializamos la variable de nivel de unidad (paso 1, lnea 27). Delphi inicializa todos los objetos de datos cuando un objeto es creado, y as no necesitamos inicializar el campo de datos privado (lnea 20).

Ejemplo 3.2. Un Objeto Aplicacin


Si revisamos nuestra experiencia con objetos RAD (p.ej., ejemplo 1.3, paso 7) vemos que tres pasos son necesarios antes de que un objeto pueda ser utilizado: 1. Definir la clase. Estipulamos los datos y mtodos requeridos (la signatura o firma de la clase) y definimos la implementacin de los mtodos. La definicin de clase proporciona un juego de instrucciones para instanciar un objeto. 2. Declaramos un nombre a usar como referencia para acceder al objeto. Esto establece la reserva de memoria en la pila para referenciar al objeto. 3. Crear el objeto. Esto reserva e inicializa memoria para el objeto en la pila, y asigna la direccin del objeto a la referencia. Adaptar estos pasos para crear nuestras propias clases y objetos es el objetivo de ste ejemplo.

Ejemplo 3.2 paso 2: Definiendo la clase TItem


Podemos usar objetos generados va RAD como punto de partida para crear nuestros propios objetos. Por ejemplo, si miramos el programa del ejemplo 3.1, vemos que Delphi deriv el formulario que nosotros creamos, TfrmCount, desde TForm. Luego list los datos (gpbItems bmbReset) y los mtodos (procedures btnItemsClick bmbResetClick).
type TfrmCount = gpbItems: lblTotal: btnItems: class(TForm) // derivado desde TForm TGroupBox; // campos de datos TLabel; TButton;

Aprendiendo OOP con Delphi

Pgina 5 de 28

Creado el 16/06/09

btnDisplay: TButton; bmbReset: TBitBtn; procedure btnItemsClick(Sender: TObject); // mtodos procedure btnDisplayMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure btnDisplayMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure bmbResetClick(Sender: TObject); private // especificador de visibilidad { declaraciones Privadas } public { declaraciones Pblicas } end;

Definiremos una clase aplicacin, TItem, para registrar el nmero de elementos del problema anterior. Desde el ejemplo 3.1, vimos que TItem necesitar un campo de datos (privado), al que llamaremos Count, y mtodos (pblicos) para aadir 1 a Count (un procedimiento), para obtener el valor de Count (una funcin) y para poner a cero el valor de Count (un procedimiento). La Figura 3 representa esto en un diagrama de clase.

Figura 3: La clase TItem

Debido a que la orientacin a objetos es encapsulacin y mantenimiento de datos y funcionamiento de las clases privadas, creamos sta nueva clase en una unidad separada. As la unidad existente que acompaa a frmCount contendr la interfaz de usuario y comunicar con la unit separada que contiene el objeto que est contando los elementos. Abra el archivo de proyecto del ejemplo 3.1. Almacene el fichero unit como OODriverU. Almacene el fichero de proyecto como OODriverP. Necesitamos una segunda unit (sin formulario) para la definicin de la clase TItem. Seleccione File | New | Unit desde el men2. Esta unit no tiene formulario y Delphi proporciona slo el nombre de la unit y el esqueleto para las secciones de interfaz e implementacin:
unit Unit2; interface implementation end.

Con clases RAD Delphi genera la definicin de clases y el esqueleto para cada mtodo. Cuando creamos nuestras propias clases podemos hacer esto manualmente. Aadimos la declaracin de clase TItem a la seccin interface y sus tres mtodos (AddItem, GetCount y ZeroCount) a la seccin implementation. Lo almacenamos como ItemU.pas
1 unit ItemU;
2 La secuencia de adicin de units vara entre versiones de Delphi. D8 ?? **

Aprendiendo OOP con Delphi

Pgina 6 de 28

Creado el 16/06/09

2 interface 3 type 4 TItem = class(TObject) // derivado desde TObject 5 private 6 FCount: integer; // el dato es normalmente privado 7 public 8 procedure AddItem; // mtodos de acceso pblicos 9 function GetCount: integer; 10 procedure ZeroCount; 11 end; // fin de TItem = class(TObject) 12 implementation 13 14 15 16 17 { TItem } procedure TItem.AddItem; begin Inc (FCount); end; // fin de procedure TItem.AddItem

18 function TItem.GetCount: integer; 19 begin 20 Result := FCount; 21 end; // fin de function Titem.GetCount 22 procedure TItem.ZeroCount; 23 begin 24 FCount := 0; 25 end; // fin de procedure Titem.ZeroCount 26 end. // fin de unit ItemU

Las declaraciones de tipo (lneas 311) son como la declaracin automtica de formularios de Delphi. La lnea 4 establece que estamos definiendo una nueva clase, TItem, la cual es derivada desde TObject, la clase base de Delphi. Los objetos TItem tendrn un campo de datos, FCount de tipo integer (lnea 6), el cual hemos hecho privado para sta unit (lnea 5).
TItem tiene tres mtodos, todos los cuales son pblicos (lnea 7) y por ello estn disponibles para el resto de units de ste proyecto. Estos mtodos pblicos proporcionan al resto de objetos una forma de interactuar con el campo de datos privado, y por ello son llamados mtodos de acceso. La lnea 8 establece que TItem tiene un tipo de procedimiento llamado AddItem que no tiene parmetros. La lnea 9 declara un mtodo tipo funcin, GetCount, que no tiene parmetros de entrada y que proporciona un valor integer (un mtodo de acceso de ste formulario es a veces llamado un mtodo Getter). La lnea 10 declara otro mtodo tipo procedimiento, ZeroCount, que no tiene parmetros de entrada.

Los mtodos estn definidos en la seccin de implementacin (lneas 12-26). Debido a que el procedimiento AddItem es uno de los mtodos de TItem, y por tanto es parte de TItem, usamos notacin de puntos para incluir la relacin con TItem en la cabecera del procedimiento (lnea 14). la lnea 16 incrementa el valor de la variable (privada) FCount declarada en la lnea 6 en uno. El mtodo ZeroCount (lneas 2225), es similar. No tiene parmetros de entrada y establece el valor de a 0. Advierta que FCount no est declarado como variable local ni siquiera en la funcin. Se declara como parte de la clase TItem en la lnea 6 y ambos mtodos manipulan ste valor. Sin embargo, debido a que FCount es declarado como privado (lneas 56), otras units no pueden acceder a Fcount.
FCount

El mtodo que queda, la funcin GetCount, retorna el valor de FCount a travs de la variable (automtica) Result (lnea 20). La nica forma en que un agente externo podra manipular el valor de FCount es a travs de los dos mtodos pblicos AddItems y ZeroCount. La nica forma en que un agente externo puede acceder a ste valor es a travs del mtodo pblico GetCount.

Aprendiendo OOP con Delphi

Pgina 7 de 28

Creado el 16/06/09

Advierta que cambiamos el nombre de Count a FCount. Debido a una convencin de Delphi, los campos de datos de clases son precedidos por F para proporcionar una rpida pista visual de que esos son campos de datos locales, y para distinguirlos de las propiedades, las cuales no tienen el cartacter precedente F. Veremos ms sobre esto en el captulo 4, donde introduciremos las propiedades y veremos las relaciones entre una propiedad y un campo de datos privado. Resumiendo. Nuestro dato, FCount, es ahora pivado y est encapsulado (lneas 5-6). la nica manera de que otra unit pueda acceder a sus datos es a travs de los mtodos de acceso pblicos AddItem, GetCount y ZeroCount (lneas 711), los cuales definen estrictamente qu operaciones pueden ser realizadas sobre el dato privado. Para reforzar que ahora tenemos dos units separadas en el proyecto, vea la clusula uses en el fichero de proyecto (secuencia de men View | Units | OODriverP). Vemos que slo un form es creado , ya que la unit ItemU.pas no posee un formulario que la acompae.
program OODriverP; uses Forms, OODriverU in 'OODriverU.pas' {frmCount}, ItemU in 'ItemU .pas'; {$R *.res} begin Application.Initialize; Application.CreateForm(TfrmCount, frmCount); Application.Run; end.

Ejemplo 3.2 paso 2: Declarando una Referencia y Creando un Objeto


Como ya mencionamos en la introduccin al ejemplo 3.2, el segundo paso a la hora de usar objetos es crear un nombre, o referencia, para cada objeto que necesitemos utilizar (p.ej., en la unit OODriverU, no en la unit ItemU). El tercer paso es crear el objeto para que podamos usarlo. Realizaremos ambos pasos aqu. En OODriverU.pas, la unit asociada con el formulario, instanciaremos un objeto de clase TItem y luego manipularemos ste objeto desde los manejadores de evento asociados a los botones. Para hacer esto, primero seleccione la pestaa OODriverU en la ventana de edicin para displayar la unit OODriverU.pas. Necesitamos que haga lo siguiente:

Aada una referencia a la otra unit (lneas 2526 debajo) porque sta unit usa una clase (TItem) que est definida en la unit ItemU. Podemos teclear sta referencia directamente o decirle a Delphi que lo haga por nosotros, a travs de la secuencia de men File | Use Unit. Declare una referencia al objeto el cual vamos a crear (ItemCount, lneas 2728). Cree el objeto en la seccin de inicializacin de OODriverU (lneas 4748). Cuando usamos componentes, Delphi crea los objetos automticamente. Sin embargo, si definimos una clase por nosotros mismos, tal como TItem, debemos crear a mano un objeto para esta clase antes de que podamos usarlo. Aqu es conveniente crear ste objeto (ItemCount) en la seccin de inicializacin, de forma que exista al mismo tiempo que aparece el formulario. Para hacer esto usaremos el mtodo constructor Create, que TItem hereda de TObject (lnea 48) (construiremos nuestro propio constructor en el captulo 5).

Aprendiendo OOP con Delphi

Pgina 8 de 28

Creado el 16/06/09

Use el objeto en los manejadores de evento OnClick a travs de las llamadas a sus mtodos. Dependiendo de la operacin que necesitemos, llamaremos al mtodo AddItem (lnea 31) o al mtodo ZeroCount (lnea 45). usaremos el mtodo GetCount, que suministra un integer, para construir el Caption del Label (lnea 36).
23 implementation 24 {$R *.dfm} 25 uses 26 ItemU ; 27 var 28 ItemCount: Titem; 29 procedure TfrmCount.btnItemsClick(Sender: TObject); 30 begin 31 ItemCount.AddItem; 32 end; // fin de procedure TfrmCount.btnItemsClick 33 procedure TfrmCount.btnDisplayMouseDown(Sender: TObject; 34 Button: TMouseButton; Shift: TShiftState; X, Y: Integer); 35 begin 36 lblTotal.Caption := IntToStr(ItemCount.GetCount); 37 end; // fin de procedure TfrmCount.btnDisplayMouseDown 38 procedure TfrmCount.btnDisplayMouseUp(Sender: TObject; 39 Button: TMouseButton; Shift: TShiftState; X, Y: Integer); 40 begin 41 lblTotal.Caption := ''; 42 end; // fin de procedure TfrmCount.btnDisplayMouseUp 43 procedure TfrmCount.bmbResetClick(Sender: TObject); 44 begin 45 ItemCount.ZeroCount; 46 end; // fin de procedure TfrmCount.bmResetClick 47 initialization 48 ItemCount := Titem.Create; 49 end. // fin de unit OODriverU

El constructor TItem.Create, llamado en la lnea 48, reserva memoria para mantener el objeto, inicializa los campos de datos del objeto y retorna la direccin del objeto que acaba de crear. As es como tpicamente creamos el objeto y asignamos el valor de retorno al nombre que que habamos declarado (la referencia) en un programa de una nica fase. Esto crea tanto el objeto como el enlace entre el nombre del objeto y el objeto mismo:
ItemCount := TItem.Create;

Advierta que creamos (instanciamos) un objeto desde una clase. As, cuando creamos un objeto llamamos al mtodo de clase Create (TItem.Create, lnea 48) y lo asignamos al nombre objeto declarado en la declaracin de variable (lnea 28). Cuando usamos un objeto, una vez que ha sido creado, las llamadas de mtodo son para ese objeto (ItemCount.AddItem en lnea 31, ItemCount.GetCount en linea 36 y ItemCount.ZeroCount en lnea 45, y no TItem.AddItem, etc). Almacene todo el cdigo del ejemplo 3.2. Ejecute y testee el programa.

Aprendiendo OOP con Delphi

Pgina 9 de 28

Creado el 16/06/09

Si desea saber (tracear) lo que est pasando en el programa, vuelva al editor y coloque puntos de ruptura en los cuerpos de los manejadores de evento OnClick (lneas 31, 36 y 45 en OODriverU.pas) (Para colocar un punto de ruptura, coloque el cursor en la lnea deseada y pulse <F5>). Ejecute de nuevo el programa. Pulse sobre los distintos botones, y ejecute el programa lnea a lnea usando <F7> y vea cmo la ejecucin se mueve entre las units. Recupere el funcionamiento normal mediante <F9>.

Ejemplo 3.2 paso 3: Diagramas UML


El diagrama de clase para ste proyecto tiene dos clases (Figura 4):

Figura 4: Diagrama TItem y TfrmCountclass

Un diagrama de secuencia contiene operaciones simples entre el usuario y estas dos clases (Figura 5). Ya que estas interacciones son flujos de mensajes y no de datos, no mostramos el dato retornado.

Aprendiendo OOP con Delphi

Pgina 10 de 28

Creado el 16/06/09

Figura 5: Iteraccin entre el usuario, frmCount y ItemCount

Ejemplo 3.2 paso 4: Beneficios de la Encapsulacin


Este ejemplo ilustra cmo un objeto puede almacenar y manipular datos. Si el dato en el objeto es declarado como privado, como lo est aqu, las nicas operaciones sobre el dato que son posibles son aquellos puestos a disposicin a travs de los mtodos pblicos. As en OODriverU no podemos ya usar nunca ms un estamento como Inc(FCount) como pusimos en el ejemplo 3.1 ya que retornar un error fatal undeclared identifier para FCount.
procedure TfrmCount.btnAddItemsClick(Sender: TObject); begin Inc(ItemCount.FCount); // Fatal, unknown identifier error end; // end procedure TfrmCount.btnItemsClick

Para lograr la encapsulacin, declaramos los datos en una clase como privados. Si hacemos los datos pblicos, estos pueden ser accedidos desde el exterior del objeto y el estamento anterior funcionar, lo cual niega completamente los beneficios de la encapsulacin.
TItem = class(TObject) public FCount: integer; // WRONG! public data, so lose encapsulation procedure AddItem; function GetCount: integer; procedure ZeroCount; end; // end TItem = class(TObject)

Aprendiendo OOP con Delphi

Pgina 11 de 28

Creado el 16/06/09

En lugar del estamento Inc(ItemCount.FCount) enviaremos el mensaje AddItem al objeto ItemCount (lnea 31). La codificacin por separado de sta clase introduce una separacin de capacidades entre la interfaz de usuario y la lgica de la aplicacin. La interfaz de usuario ahora simplemente especifica qu necesita ser hecho, aadir un elemento, sin que le concierna el cmo hacerlo. El objeto ItemCount simplemente sabe que cuando reciba un mensaje AddItem, debe incrementar el valor de FCount. No necesita saber nada sobre el evento que lanz el mensaje AddItems.

Ejercicio 3.2 paso 5: El Explorador de Cdigo


El Explorador de Cdigo displaya un diagrama mostrando las clases y mtodos definidos en la unit displayada por el editor. Est ubicado a la izquierda del editor en las versiones de Delphi anteriores a la 7. Utilice la secuencia de men View | Code Explorer en Delphi 8. Si expandimos el rbol, el Explorador de Cdigo nos da una til vista grfica de la clase TItem que hemos definido, mostrando el campo de datos privado, FCount, y los mtodos pblicos , AddItem, GetCount y ZeroCount (Figura 8). El Explorador de Cdigo proporciona una forma rpida de navegar por una unit. Haciendo doble click en cualquiera de los nodos del rbol, vamos directamente a la definicin de cdigo para ese nodo.

Ejemplo 3.2: Sumario


Hay tres pasos en el proceso de definicin de una clase y la creacin de un objeto:

Primero definimos la estructura de la clase y la implementacin de los mtodos (como gua, podemos imitar la forma en que Delphi define el form en un fichero unit). Segundo, reservamos un nombre (el cual acta como su referencia) para un objeto de clase listndolo en la declaracin de variables de la unit que va a usar el objeto (y no en la unit donde se define la clase, como hace el RAD). Tercero, activamente instrumos a Delphi para crear el objeto y asignarlo al nombre que hemos declarado, de forma que podamos usarlo en nuestro programa.

Una vez completados estos pasos podemos continuar y usar el objeto a travs de llamadas a sus mtodos. Estos usan la notacin estndar del punto, con el nombre del objeto seguido del nombre del mtodo y cualesquiera parmetros que sean necesarios.

Ejemplo 3.3: Subclaseado y Herencia


Asumamos que ahora necesitamos mejorar el programa del ejemplo 3.2 para acomodar cajas de 4 elementos, as como elementos sueltos (Figura 6).

Figura 6: Mejorando la funcionalidad

Figura 7: Los objetos en la interfaz de usuario

Aprendiendo OOP con Delphi

Pgina 12 de 28

Creado el 16/06/09

Varias opciones funcionarn. Podemos tener la llamada a AddItem en el manejador de eventos OnClick del btnAddBox cuatro veces:
procedure TfrmCount.btnBoxClick(Sender: TObject); begin // una pobre aproximacin ItemCount.AddItem; ItemCount.AddItem; ItemCount.AddItem; ItemCount.AddItem; end;

Esto, o algo parecido a un bucle For, no es una buena idea ya que perdemos la separacin de conceptos -la interfaz de usuario debe conocer que una caja contiene cuatro elementos-. Otra posibilidad es aadir un mtodo AddBox a la clase TItem. Esta es una mucho mejor aproximacin. Una tercera alternativa es crear una subclase de TItem conteniendo un mtodo AddBox. Ambas alternativas mantienen la separacin de capacidades, mientras que el tercer mtodo adems clarifica la distincin entre Elemento y Caja.

Figura 8: El Explorador de Cdigo y el Editor de Cdigo en Delphi 6

Ejemplo 3.3 paso 1: Subclaseando TItem


Nosotros desarrollamos el cdigo del ejemplo 3.2 para crear la subclase de TItem. El primer paso es definir la subclase TItemBox. Podemos crearla tanto en la unit existente ItemU como en una unit nueva. Por simplicidad, extenderemos la unit existente ItemU.
1 unit ItemU; 2 interface 3 type 4 TItem = class(TObject) 5 private 6 FCount: integer; 7 public 8 procedure AddItem; 9 function GetCount: integer; 10 procedure ZeroCount; 11 end; // end TItem = class(TObject) 12 TItemBox = class(TItem) // Derived from TItem, not TObject

Aprendiendo OOP con Delphi

Pgina 13 de 28

Creado el 16/06/09

13 public 14 procedure AddBox; // Public access method 15 end; // end TItemBox = class(TItem) 16 implementation 17 18 19 20 21 { TItem } procedure TItem.AddItem; begin Inc(FCount); end; // end procedure TItem.AddItem

22 function TItem.GetCount: integer; 23 begin 24 Result := FCount; 25 end; // end function Titem.GetCount 26 procedure TItem.ZeroCount; 27 begin 28 FCount := 0; 29 end; // end procedure Titem.ZeroCount 30 31 32 33 34 35 36 { TItemBox } procedure TItemBox.AddBox; const NoInBox = 4; begin Inc (FCount, NoInBox); end; // end procedure TitemBox.AddBox

37 end. // end unit ItemU

Aqu, en adicin a la definicin de TItem (lneas 411) que tenamos previamente, definimos una nueva clase llamada TItemBox (lneas 1215). Mientras que TItem est derivado de TObject (lnea 4), TItemBox est derivado de TItem (lnea 12). TItemBox es una subclase de TItem y por ello hereda todos los datos y mtodos que tiene TItem. Este es un simple ejemplo de reutilizacin en OO -toda la funcionalidad del TItem est disponible en el TItemBox sin reescribir ni una sla lnea de cdigo-. TitemBox tambin tiene su propio mtodo, el procedimiento AddGoal declarado en la lnea 14. En la seccin de implementacin (lneas 1636) los mtodos del TItem AddItems, GetCount y permanecen como antes. Las lneas 3136 definen el mtodo del TitemBox AddBox, el cual incrementa el valor de FCount (definido en la superclase TItem).
ZeroCount

Aprendiendo OOP con Delphi

Pgina 14 de 28

Creado el 16/06/09

Figura 9: Aadiendo la subclase TItemBox al diagrama de clase

Ya que TItemBox usa el campo de datos FCount definido en el TItem no necesitamos reimplementar el para TItemBox sino simplemente basarnos en la definicin heredada. Ya que la herencia trabaja slo en una direccin TItemBox tiene los datos y mtodos de TItem como parte de su estructura, pero TItem no tiene el mtodo AddBox que est declarado en TitemBox.
ZeroCount

Aunque los mtodos tanto para TItem como para TItemBox aparecen en la seccin de implementacin de sta unit, Delphi los distingue mediante sus cabeceras, ya que la clase aparece antes del punto en los nombres. Advierta que aunque FCount est declarado como privado para TItems, TBoxItems puede acceder a l. Esto es debido a que los especificadores de visibilidad private, protected y public en Delphi se aplican a la unit en lugar de a la clase. Desde Delphi 8, Delphi tambin tiene strictly private y strictly protected que se aplican a la clase est o no empaquetada en la misma unit como otra clase. El diagrama de clase ahora incluye la nueva subclase TItemBox (Figura 9).

Ejemplo 3.3 paso 2: Usando la nueva subclase


Aadimos btnBox al form (Figura 6 y Figura 7). En la unit OODriverU.pas cambiamos el tipo del objeto a TItemBox (lnea 30 debajo), creamos ItemCount desde TItemBox en vez de TItem (lnea 52), y aadimos un manejador de evento OnClick para btnBox que llama al nuevo mtodo AddBox (lneas 4750).
ItemCount 26 implementation 27 uses 28 ItemU ; 29 var 30 ItemCount: TItemBox; // Change to TitemBox 31 { Event handlers as before } 47 procedure TfrmCount.btnAddBoxClick(Sender: TObject); 48 begin 49 ItemCount.AddBox; 50 end; // end procedure TfrmCount.btnAddBoxClick

Aprendiendo OOP con Delphi

Pgina 15 de 28

Creado el 16/06/09

51 initialization 52 ItemCount := TItemBox.Create; 53 end. // end unit BoxCountU

Guarde todo, y luego ejecute y testee el programa.

Ejemplo 3.3: Sumario


En ste ejemplo derivamos TItemBox desde TItem y le aadimos un mtodo AddBox a TItemBox. Ya que TItemBox es una subclase de TItem, ste hereda las definiciones de los campos de datos y mtodos de TItem, y los aade a su propia definicin de mtodos (tambin podra tener ms campos de datos definidos). Mediante el subclaseado no interferimos con la clase existente TItem. Debido a que sta clase de aplicacin separada mantiene la separacin de capacidades, la interfaz de usuario no necesita saber cuntos elementos hay en una caja, sino que simplemente llama al mtodo AddBox. Si en un futuro, el empacado cambia a una caja que almacena seis unidades, la interfaz de usuario no se ve afectada ya que en su lugar simplemente cambiamos la definicin de TItemBox. A consecuencia de la herencia, toda la funcionalidad de TItem est disponible tambin a travs de
TItemBox.

Aunque ahora declaramos ItemCount como un TItemBox y no como un TItem, todos los manejadores de evento existentes permanecen igual. Creamos un nuevo manejador de evento para usar la facilidad aadida y esto usa mtodos disponibles slo para un TItemBox y no para un TItem.

Aprendiendo OOP con Delphi

Pgina 16 de 28

Creado el 16/06/09

Navegando a travs del Explorador de Cdigo


Mientras tenemos ste ejemplo an en la pantalla, nos vamos a ir brevemente al Explorador de Cdigo (Figura 10). Haga click sobre la pestaa ItemU en la ventana de edicin. Advierta que el Explorador de Cdigo ahora muestra ambas clases, TItemBox y TItem, declarados en sta unit. Como antes, podemos expandir el rbol haciendo click en los nodos y navegar a travs del cdigo de programa.

Figura 10: Usando el Explorador de Cdigo para navegar a travs del cdigo

El Navegador de Proyecto
Ni el Explorador de Cdigo (Figura 10) ni el Visor de Objetos (Figura 7) muestran la jerarqua de herencia de clases, as que echaremos un breve vistazo al Navegador de Proyecto de Delphi, disponible en View | Browser en versiones de Delphi inferiores o iguales a Delphi 7 (el proyecto cargado debe haberse ejecutado en la sesin actual antes de que la opcin del navegador se vuelva disponible). El Navegador de Proyecto muestra las clases que hemos creado en ste proyecto junto con su estructura de herencia (Figura 11, panel izquierdo). Vemos TObject como la clase principal con TItem derivado desde TObject y TItemBox derivado a su vez desde TItem. Tambin vemos que el formulario que creamos, TfrmCount, est derivado desde TForm, el cual a su vez est derivado desde una serie de otros objetos todos nacidos de TObject (vimos la herencia VCL de Delphi en el captulo 2). Si seleccionamos TItemBox en el panel izquierdo, en el panel derecho vemos que TItemBox tiene un nico miembro pblico, el mtodo AddBox. ste ha heredado el campo de datos privado, FCount, y un lote de mtodos pblicos heredados desde TItem y TObject incluyendo al constructor Create cerca del final (bottom) del panel. El navegador tiene muchas ms capacidades. Para ms informacin presione <F1> mientras el navegador es la ventana activa.

Aprendiendo OOP con Delphi

Pgina 17 de 28

Creado el 16/06/09

Figura 11: El navegador de proyecto de Delphi mostrando tanto las clases estndar de Delphi como las definidas localmente

Ejemplo 3.4: Mtodos Sobrecargados y Visibilidad Protegida


Algunos programadores OO piensan que no debera poder accederse a campos de datos definidos en una superclase directamente desde una subclase. Ellos no estaran contentos con nuestra definicin del mtodo AddBox del TBoxItem en el ejemplo 3.3, paso 1 lnea 35, ya que ste accede directamente al campo de datos FCount de la superclase. En su lugar, para proteger la encapsulacin, ellos piensan que una subclase siempre debera usar los mtodos de acceso de la superclase para acceder a sus campos de datos. Podemos redefinir AddBox de una forma desordenada y poco elegante para usar AddItem:
32 33 34 35 36 37 procedure TItemBox.AddBox; var Count: integer; begin for Count := 1 to NoInBox do AddItem; end; // end procedure TItemBox.AddBox

Sera mejor, a pesar de tener un mtodo en la superclase TItem, agregar un nmero determinado de puntos en el campo Fcount. Esto lleva al concepto de mtodos sobrecargados: aadir un mtodo AddItem protegido con el nmero a aadir como parmetro (lnea 8 debajo). Esto es en adicin al mtodo AddItem que ya tenemos, aunque ste no tiene parmetros (lnea 10 debajo). As que ahora tenemos dos mtodos con el mismo nombre. Cmo distingue Delphi entre ellos? Si llamamos a AddItem sin parmetros, como en el ejemplo 3.2, paso 2, lnea 31, Delphi invocar al mtodo con el nombre requerido y sin parmetros (p.ej., lneas 2023 debajo). Si llamamos a AddItem con un nico parmetro entero, como en la lnea 41 de debajo, Delphi invocar a la implementacin del mtodo con el mismo nmero de parmetros (p.ej., lneas 2427 debajo). Para informar al compilador que estamos sobrecargando ste nombre de mtodo, debemos aadir la palabra clave overload en cada declaracin de AddItem (lneas 8 y 10 debajo). Los nombres de mtodo sobrecargados deben tener siempre diferentes listas de parmetros en trminos de tipos o nmero de parmetros, para que el compilador pueda distinguirlos cuando sean llamados.

Aprendiendo OOP con Delphi

Pgina 18 de 28

Creado el 16/06/09

Podemos evitar la sobrecarga si usamos distintos nombres, p.ej., AddItem y AddItems(). Sin embargo, en casos en los que deseamos realizar la misma operacin pero con distinto nmero o tipo de parmetros, p.ej., enteros o dobles, es particularmente til tener la capacidad de sobrecargar el mismo nombre.
1 unit ItemU; 2 interface 3 type 4 TItem = class(TObject) 5 private 6 FCount: integer; 7 protected 8 procedure AddItem (aNoToAdd: integer); overload; 9 public 10 procedure AddItem; overload; 11 function GetCount: integer; 12 procedure ZeroCount; 13 end; // end TItem = class(TObject) 14 TItemBox = class(TItem) 15 public 16 procedure AddBox; 17 end; // end TItemBox = class(TItem) 18 implementation 19 20 21 22 23 { TItem } procedure TItem.AddItem; begin Inc(FCount); end; // end procedure TItem.AddItem

24 procedure TItem.AddItem(aNoToAdd: integer); 25 begin 26 Inc(FCount, aNoToAdd); 27 end; // procedure TItem.AddItem(aNoToAdd: integer); 28 function TItem.GetCount: integer; 29 begin 30 Result := FCount; 31 end; // end function Titem.GetCount 32 procedure TItem.ZeroCount; 33 begin 34 FCount := 0; 35 end; // end procedure Titem.ZeroCount 36 37 38 39 40 41 42 { TItemBox } procedure TItemBox.AddBox; const NoInBox = 4; begin AddItem(NoInBox); end; // end procedure TitemBox.AddBox

43 end. // unit ItemU

Debido a que estos cambios estn encapsulados dentro de las clases TItem y TitemBox. La interfaz de usuario del ejemplo 3.3 no necesita alteracin para interactuar con sta unit, como ver cuando lo ejecute.

Aprendiendo OOP con Delphi

Pgina 19 de 28

Creado el 16/06/09

Advierta que AddItem sin parmetros es declarado como pblico (lnea 10 anterior) y as puede ser llamado directamente por la clase de interfaz de usuario (p.ej., ejemplo 3.2, paso 2, lnea 31). Sin embargo, AddItem con el parmetro es declarado como protegido y as no puede ser llamado por el objeto de interfaz de usuario. Para ver esto, cambie al ejemplo 3.3, paso 2, lnea 49 para llamar a AddItem:
47 procedure TfrmCount.btnBoxClick(Sender: TObject); 48 begin 49 ItemCount.AddItem(4); // out of scope 50 end; // end procedure TfrmCount.btnBoxClick

Esto provoca un error de compilador. En Delphi los especificadores de visibilidad private y protected se aplican a la unit. As en ste caso hemos reemplazado protected por private y el programa todava funcionar. Sin embargo, si stas dos clases son definidas en units separadas el procedimiento sobrecargado AddItem (aNoToAdd) no estar accesible con visibilidad privada y por tanto debe ser protegido (no queremos hacerlo pblico porque queremos que su visibilidad quede restringida a TItem y sus descendientes).

Diseo de Memoria para Clases y Objetos


Cmo aparece un objeto en memoria? La Figura 12 nos da una ilustracin simplificada del diseo de clase de la clase TItem en ItemU.pas. Obtiene todos los mtodos heredados a travs una referencia a la clase padre y entonces usa memoria adicional para los mtodos que ella declara.

Figura 12: Una versin simplificada del diseo de clase en memoria

Los nombres de objeto son actualmente referencias al bloque de memoria que almacena del dato nico para ese objeto. La declaracin del nombre reserva memoria en la pila para mantener la referencia al objeto, pero no para el objeto mismo (Figura 13).

Aprendiendo OOP con Delphi

Pgina 20 de 28

Creado el 16/06/09

Figura 13: Referencia al objeto

Cuando invocamos al objeto constructor, esto reserva memoria para almacenar el objeto mismo, inicializa los valores y proporciona el enlace a la clase (Figura 14).

Creado el 16/06/09

Figura 15: Creando el objeto y enlazndolo al nombre

El ejemplo 3.3 introduce la herencia. Esto significa que necesitamos crear una tabla adicional para los mtodos de subclase y luego enlazar a ellos nuestro objeto, tal como se ilustra en la Figura 16 (advierta que aunque no tenemos un objeto TItem en el ejemplo 3.3, an tenemos una tabla de la clase TItem).

Figura 16: Diseo de memoria de subobjeto

Aprendiendo OOP con Delphi

Pgina 22 de 28

Creado el 16/06/09

Si creamos varios objetos necesitamos repetir la tabla de objeto pero no la tabla de clase. As que si tenemos otro objeto, MoreItems, de tipo TItemBox, obtendremos la Figura 17.

Figura 17: Dos objetos TItemBox

Este otro objeto MoreItems podra ser en su lugar del tipo TItem (Figura 18) en cuyo caso ste tiene acceso a los mtodos TItem pero no a los mtodos TItemBox:

Figura 18: Un objeto TItem y otro TItemBox

En la Figura 18 ambos objetos tienen la misma estructura de datos. Esto es as porque la subclase en el ejemplo 3.3 aade mtodos adicionales pero no campos de datos adicionales a la superclase. Aadiremos campos de datos adicionales a una subclase ms adelante en ste mdulo. En suma, como se ilustra en la Figura 17, cada referencia a objeto se refiere a un bloque de datos especfico para ese objeto. As diferentes objetos de la misma clase tienen cada uno sus propios datos. Sin embargo, distintos objetos de la misma clase cada una de ellas transporta una referencia a las mismas definiciones de mtodos compartidas. Cada subclase define sus propios mtodos y lleva un puntero a sus mtodos de superclase para la definicin de los mtodos heredados, y as sucesivamente hasta la jerarqua.
Aprendiendo OOP con Delphi Pgina 23 de 28

Creado el 16/06/09

Aunque estn muy simplificados, estos diagramas son bastante complicados. Podran ser difciles de utilizar en una programacin normal. Afortunadamente, generalmente no vamos a necesitar pensar en estos trminos y podremos usar la abstraccin proporcionada por los diagramas (p.ej., la Figura 9).

Sumario del Captulo


Mantener los objetos de interfaz de usuario y de aplicacin separados: separacin de capacidades Mimetizar objetos de interfaz de usuario RAD en clases de aplicacin definidas por el usuario Pasos para usar un objeto definido por el programador:

Definir la clase, Localizar un nombre (referencia), Instanciar el objeto, Asignarle un nombre.

Herencia: derivar una nueva clase desde una existente Empaquetar una clase en una unit El Explorador de Cdigo y el Navegador de Proyecto Diseo de objetos en memoria

Puntos principales: 1. Definicin y uso de una clase y una subclase 2. Semntica de referencia y diseo de objeto en memoria 3. Separacin de capacidades: interfaz de usuario y clases de dominio

Objetos como entidades independientes: clase definida por el programador Objetos como entidades derivadas: herencia definida por el programador Objetos como entidades interactuantes: mtodos de acceso, visibilidad, sobrecarga

Aprendiendo OOP con Delphi

Pgina 24 de 28

Creado el 16/06/09

Problemas
Problema 3.1. Estudio de Captulo 3
Identifique los apropiados ejemplos o secciones del captulo para ilustrar cada comentario hecho en el sumario anterior.

Problem 3.2. Dobles Cintas Transportadoras


Extienda el ejemplo 3.3 para trabajar con un sistema de doble cinta transportadora. Una cinta mueve elementos simples y cajas de 6 elementos, mientras que la otra slo mueve elementos unitarios. Haciendo click en el botn Display se muestra el total de cada cinta, mientras que al liberar la presin del botn se ocultan los totales (Figura 19).

Figura 19: Extendiendo el ejemplo de la cinta transportadora

En la escritura de ste programa colocamos las definiciones de TItem y TItemBox en units separadas.

Problema 3.3. Distintos tamaos de caja


Considere otra variacin del problema de la cinta transportadora. En un almacn hay un rea de almacenamiento temporal, con tres cintas transportadoras reversibles. Una transporta elementos individuales, la segunda transporta cajas de 4 elementos y la tercera cajas ms grandes con 12 elementos. La pantalla se asemeja a esto (Figura 20):

Aprendiendo OOP con Delphi

Pgina 25 de 28

Creado el 16/06/09

Figura 20: Diferentes tamaos de caja

Figura 21: Componentes de interfaz de usuario para diferentes cajas

Hay varias formas de estructurar las clases de la aplicacin. Una podra ser, por ejemplo, usar una estructura fuertemente jerrquica (Figura 22) o una estructura relativamente dbil (Figura 23) .

Figura 22: una profunda, jerrquica estructura

Figura 23: Una estructura menor

1. Contraste estas dos aproximaciones, describiendo las ventajas y desventajas de cada una. 2. Implemente la versin de jerarqua profunda. 3. Implemente la versin de jerarqua dbil. Tras haber realizado estas dos implementaciones, puede encontrar que desee aadir o modificar sus comentarios en la parte 1 de sta pregunta.

Aprendiendo OOP con Delphi

Pgina 26 de 28

Creado el 16/06/09

Problema 3.4. Entrada Protegida


Escriba un sistema de acceso protegido mediante contrasea que inicialmente tenga un nico mtodo de acceso. La interfaz de usuario para la Puerta 1 (Figura 24) tiene:

una seccin de entrada de texto, la cual muestra asteriscos cuando se escribe texto, un botn para enviar la clave y un rea de respuesta.

Si la contrasea es correcta, la respuesta es Proceda (Figura 24). Si la contrasea es incorrecta, la respuesta es Reporte a escritorio principal.

Figura 24: Contrasea de Primer Nivel

De acuerdo con el Principio de Separacin de Capacidades, la interfaz de usuario estar separada de la clase aplicacin (TVerify) para determinar si la contrasea es correcta o no (Figura 26). La interfaz de usuario enva un mensaje al objeto aplicacin dando una clave (la cual representa la contrasea correcta) y la palabra introducida por el usuario. El objeto de verificacin de la contrasea entonces retorna True o False. Actualmente el algoritmo de verificacin es muy simple: el usuario debe introducir el reverso de los que es la clave. As que si la clave es Mary, el usuario debe introducir yraM como contrasea. La Figura 25 muestra los componentes en la interfaz de usario, y la Figura 26 presenta un diagrama de clase. Escriba ste programa. La clave debera ser Mary, con units separadas para TfrmPassword (Figura 24) y para TVerify.

Figura 25: Los componentes de la interfaz de usuario

Figura 26: Diagrama de clase para control de clave de primer nivel

Aprendiendo OOP con Delphi

Pgina 27 de 28

Creado el 16/06/09

El sistema ahora puede ser extendido. La primera puerta de acceso permanece como antes (Figura 24). una segunda puerta con una segunda, separada interfaz de usuario como la interfaz de la primera puerta es aadida. Esta segunda puerta de acceso tiene dos niveles de chequeo de contrasea. Si el usuario introduce la primera clave correctamente en la segunda puerta, el sistema entonces displaya un form adicional solicitando al usuario una segunda, distinta contrasea (Figura 27). Slo si sta tambin es correcta se permite al usuario proceder. Si la primera clave es incorrecta, o si la primera es correcta pero la segunda no, el usuario debe recibir el mensaje Reporte a Escritorio Principal. El diagrama de clase se muestra en la Figura 28. Escriba ste programa. La primera clave es Mary y la segunda es George. El programa actualizado ahora tiene cuatro units separadas, una para la primera puerta (TfrmPassword, Figura 24), para la segunda (TfrmPassword1 derivado desde TfrmPassword), para el formulario adicional TfrmPassword2 (Figura 27) y para TVerify.

Figura 27: La pantalla de entrada adicional (para la segunda clave) Figura 28: Diagrama de clase para control de clave de segundo nivel

Histrico de Cambios
1. Problema 3.2 se refiere a ejemplo 3.3. 2. Nueva figura insertada (Figura 21). La figuras subsecuentes se incrementan de nmero apropiadamente. 3. Pgina 9, prrafo final: Advierta que hemos cambiado el nombre FCount a FCount Cambiado a ...Count to FCount.

Aprendiendo OOP con Delphi

Pgina 28 de 28

También podría gustarte