Vous êtes sur la page 1sur 147

Leccin 1

Presentando REALbasic

Objetivo En esta leccin aprenders a crear y ejecutar una aplicacin de REALbasic sencilla. Tambin aprenders parte de lo que ocurre entre bastidores en REALbasic. Recuerda: El proyecto de Enseanza de REALbasic tiene como objeto ensearte ciencia de la computacin, de modo que no cubriremos las capacidades de REALbasic en detalle. Existen otros muchos lugares en los que puedes obtener dicha informacin, empezando con la propia documentacin de REALbasic. Crear el proyecto 1 Haz doble clic sobre el icono de REALbasic para ejecutar el software. REALbasic abre la ventana principal correspondiente al Entorno de Desarrollo Integrado (IDE): Figura 1. La Ventana de Proyecto. (captura Figura 1) Esta ventana contiene todos los elementos de tu proyecto. La primera pantalla que ves contiene el Editor de Proyecto. El IDE de REALbasic est compuesto por varios editores presentados mediante paneles accesibles desde las correspondientes pestaas. El Editor de Proyecto se abre automticamente cada vez que creas un nuevo proyecto o abres alguno de los proyectos existentes. Puedes tener abierta ms de una de estas ventanas para cada proyecto, adems de poder mantener abiertos varios proyectos simultneamente si as lo deseas. Sin embargo, probablemente realices la mayora de tu trabajo con REALbasic en slo una de estas ventanas. Puede trabajar en una ventana dado que puedes abrir varias pestaas (de forma muy similar a como utilizas un navegador web) para ver diferentes partes de tu proyecto. Dado que te has limitado a ejecutar REALbasic sin abrir un proyecto ya existente, REALbasic te ha ayudado creando un nuevo proyecto con algunos elementos de inicio ya listos en l. La pestaa que ves justo ahora es la correspondiente al Editor de Proyecto, desde el que puedes acceder a todas las partes de tu proyecto de REALbasic. 2. Haz doble clic sobre el elemento Window1 en el Editor de Proyecto. Esta accin abre una nueva pestaa Window1 en la que se muestra el Editor de Ventana, listo para que aadas controles sobre ella. Figura 2. El Editor de Ventana (Captura Figura 2) Advierte que aun puedes ver la pestaa correspondiente al Editor de Proyecto bajo la barra de herramientas, y de hecho puedes hacer clic sobre ella y la pestaa correspondiente a Window1 para cambiar entre ambas. Advierte tambin que la pestaa correspondiente a Window1 tiene un elemento de cierre justo en la parte derecha. Al cerrar una pestaa slo se cierra el editor; todos los objetos del programa permanecen hasta que los borres en el Editor de Proyecto. Siempre puedes volver a abrir un editor

buscando el objeto que quieras editar en la pestaa Proyecto y haciendo doble clic sobre l. En el centro del Editor de Ventana vers una ventana vaca, lista para su edicin. A su izquierda vers el listado de Controles, desde el que puedes arrastrar cualquier control que quieras aadir a la ventana, como por ejemplo botones, etiquetas, y cajas de texto en las que el usuario puede introducir informacin, etc: Figura 3. El listado de Controles. (captura Figura 3) El men desplegable de la parte superior del listado de Controles te permite alternar entre los controles incluidos de serie en REALbasic, aquellos que hayas aadido mediante Plugins, los que hayas creado t mismo, y tus Favoritos. Durante nuestras lecciones utilizaremos slo algunos de todos los controles disponibles en este listado, pero explicaremos como funciona cada uno de ellos a medida que los vayamos necesitando. Consulta la Gua del Usuariopara obtener ms detalles sobre la funcin de cada uno de estos controles y sobre cmo crear tus propios controles personalizados. 3 Arrastra un control StaticText en la parte superior izquierda de la ventana (probablemente tendrs que desplazarte por el listado de Controles para encontrarlo). Figura 4. El control StaticText. (Captura Figura 4) Una vez que lo hayas soltado, arrstralo un poco ms. Advierte como REALbasic muestra guas de alineacin y ajusta hacia el punto de la derecha para ayudarte a situar los elementos ajustndose a las Guas de Interfaz de Usuario especcas de tu plataforma. (Ten en cuenta que REALbasic Professional y REAL Studio pueden crear programas para Macintosh, Windows o Linux a partir de un nico cdigo fuente. Y no tienes por qu ejecutar REALbasic en cada plataforma para la que quieras crear el programa; si bien es conveniente que lo hagas para labores de testeo. No hablaremos ms sobre este aspecto en las siguientes lecciones; conulta la informacin disponible en la Gua del Usuario para obtener ms informacin. El panel Propiedades, que est en la parte derecha del Editor de Ventana, te permite gestionar los ajustes para los cntroles que estn seleccionados en la ventana o bien de la propia ventana: Figura 5. El panel de Propiedades. (captura Figura 5) La mayora de estos ajustes son obvios; no te preocupes por ahora sobre aquellos que no resultan tan evidentes. Haz clic sobre la propiedad Text: y cmbialo para que se corresponda con Nombre: (sin las comillas, slo como ves en la Figura 5). Advierte que

puedes hacer clic en un rea de la ventana que no contiene controles para gestionar las propiedades correspondientes a la ventana propiamente dicha. Ten en cuenta tambin que puedes modicar el tamao de la ventana una vez que la tengas seleccionada. 4 Arrastra un control TextField en la ventana a la derecha del control StaticText: Figura 6. El control TextField. 5 Cambia su Name: a UserName (una palabra, sin espacios, y sin las comillas). 6 Arrastra un control PushButton en la parte inferior derecha de la ventana: Figura 7. El Control PushButton. (Captura Figura 7) A medida que lo arrastres por la esquina inferior derecha de la ventana, aparecern guas horizontales y verticales. 7 Cambia su propiedad Caption a Greet Me. Probablemente necesitars hacer que el botn sea un poco ms ancho para que encaje el texto de la etiqueta. Ten en cuenta que puedes cambiar la posicin y tamao de los elementos de la ventan utilizando las mismas tcnicas que se emplean en un programa de dibujo. 8 Haz doble clic sobre el PushButton. Esta accin te llevar al Editor de Ventana de modo que pasars del modo de diseo al modo de edicin de los objetos. Tambin puedes cambiar entre el editor de Diseo y el Editor de Cdigo haciendo clic sobre el botn Modo de Edicin que no est seleccionando en ese momento. En la Figura 8 est seleccionado el Editor de Cdigo. Figura 8. Botones del Modo de Edicin. (captura Figura 8) Los botones del Modo de Edicin cambian del modo de edicin de plantilla (lado derecho del control seleccionado) al modo de edicin de cdigo (lado de la izquierda seleccionado). Tambin puedes cambiar entre los dos haciendo clic sobre el control. En la platforma Windows, el modo seleccionado aparece pulsado en vez de seleccionado. El Editor de Cdigo te permite ver todo el cdigo que hayas aadido directamente a la ventana o a los controles contenidos en ella (posteriormente veremos que por lo general algunos o incluso la mayora del cdigo que gobierna el comportamiento de la ventana y los controles pueden residir en otras parte, pero por ahora no te preocupes de esto). El Editor de Cdigo se abrir para el Evento ms adecuado correspondiente al control sobre el que hayas hecho doble clic. Figura 9. El panel del Editor de Cdigo. (Captura Figura 9)

Advierte que el Editor de Cdigo te permite editar el cdigo del programa para cada control de la ventana,a s como otros aspectos que pertenecen a la ventana, utilizando para ello el navegador de la parte izquierda del rea correspondiente al editor de cdigo. En Windows, puedes expandir los elementos haciendo clic sobre el signo ms y, en Macintosh y Linux, puedes hacer clic sobre el tringulo de despliegue. Prueba a hacer clic sobre algunos de los pequeos signos de ms o tringulos de despliegue del navegador y comprueba los resultados. Por ahora, slo necesitas entender que todos los controles de la ventana pueden contener cdigo de REALbasic para indicarle qu debe hacer cuando ocurra una accin en particular. En el ejemplo mostrado, se indica al botn lo que debe hacer cuando se haga clic sobre l (es decir, cuando ocurra un evento de Action o Accin). Escribe el cdigo tal y como se muestra en la imagen: MsgBox UserName.Text A medida que empieces a escribir la palabra MsgBox, REALbasic intentar anticiparse a lo que ests tecleando, y completar el resto de la palabra: Figura 10. Completacin de cdigo. (captura Figura 10) Cada vez que REALbasic haga esto puedes pulsar la tecla Tab para aceptar la sguerencia destacada por REALbasic, o bien seleccionar otra opcin de las mostradas en el listado en el caso de que exista ms de una, para completar el trmino que se est introduciendo. Ten en cuenta que slo hay un espacio en dicha lnea, entre MsgBox y UserName.Text (en particular, slo un punto y sin espacio entre UserName y Text). Un apunte: El cdigo de programa de REALbasic no distingue entre maysculas y minsculas. Esto signica que puedes utilizar maysculas, minsculas o una combinacin de ambas y el cdigo seguir funcionando. Y una ltima cosa: si haces clic sobre el rea gris disponible en la zona izquierda de la lnea de cdigo, entonces vers que aparece un punto. Esta accin dene un punto de parada (breakpoint)en tu cdigo. Hasta que veamos los puntos de parada en la Leccin 3, slo encrgate de hacer clic sobre el punto rojo para que desaparezca de nuevo. 9 Guarda tu proyecto, tal y como haras con cualquier archivo de otro programa. Si ejecutas un programa tras modicarlo y sin guardarlo previamente, REALbasic se encargar de guardar automticamente una copia oculta, slo por si algo va mal mientras se est ejecutando el programa (si REALbasic se cuelga, slo has de ejecutar REALbasic de nuevo y este te ofrecer la posibilidad de recuperar la copia oculta). Pero todo resulta un poco ms sencillo si te acuerdas de guardar los proyectos por ti mismo. Adems volveremos a utilizar este proyecto de nuevo, de modo que asegrate de recordar donde lo has guardado. 10 Haz clic sobre el botn Ejecutar de la barra de herramientas: (Captura Figura 10)

11 REALbasic abrir una nueva pestaa de Ejecucin, en la que te mostrar el progreso a medida que REALbasic compile la aplicacin. Tambin te permitir interactuar con el programa mientras se ejecute mediante el depurador (debugger) de REALbasic. Veremos el depurador en el Captulo 3. Si REALbasic no puede compilar la aplicacin te mostrar los errores que encuentre y que han evitado su compilacin. En el caso de que REALbasic te muestre cualquier error regresar de nuevo a la pestaa de Ejecucin y destacar la lnea en la que se ha encontrado el error. Compureba que has tecleado correctamente el cdigo, soluciona el problema e intntalo de nuevo. Cuando la aplicacin no tiene errores, REALbasic compilar y ejecutar el programa en su propia ventana. Mientras tanto, la pestaa Ejecucin del IDE te permitir monitorizar la ejecucin en el depurador. Figura 12. Tu primera aplicacin REALbasic. (captura Figura 12) Cuando el programa se jecute, escribe cualquier cosa en el campo de texto y haz clic sobre el botn Greet Me. Te mostrar exctamente lo que hayas tecleado dentro de un cuadro de dilogo. Haz clic en OK para cerrar el cuadro de dilogo, y selecciona a continuacn Salir en el men Archivo. Esta accin te llevar de nuevo al entorno de programacin de REALbasic (de hecho, el programa y REALbasic son en realidad dos programas que se ejecutan por separado, de modo que puedes cambiar entre los dos en cualquier momento, tal y como haras entre otros dos programas de tu sistema opertivo). Un programa est formado por lneas de cdigo Ahora veremos cmo ha funcionado. Selecciona Referencia del Lenguaje en el men Ayuda. Dicha accin abrir el sistema de Ayuda de REALbasic, encargado de proporcionar una completa informacin sobre el lenguaje de programacin de REALbasic y su librera de clases (una librera de clases es una coleccin de herramientas listas para usar. Todos los elmentos del listado Controles, junto con el resto de objetos listados en la Referencia del Lenguaje en la librera de clase de REALbasic). Figura 13. La ventana de la Referencia del Lenguaje. (Captura Figura 13) Un programa de REALbasic est compuesto por una o ms lneas de cdigo. Cada lnea indica una cosa al ordenador. Dichas lneas pueden tener formas diferentes, pero lo ms comn es la mostrada en este programa: consiste de un comando (en este caso, MsgBox) al inicio de la lnea, generalmente (pero no siempre) seguido de un espacio y a continuacin uno o ms partes de informacin necesaria para que el comando tenga sentido. Dichas piezas de informacin se denominan los argumentos del comando. En este caso, el comando MsgBox necesita un nico argumento, y que proporciona el texto que se ha de mostrar.

Es posible indicar que una lnea de cdigo tenga efecto (nos referimos a que el cdigo se ejecute o corra) de varias formas diferentes. En este caso, el cdigo ha fomrado un manejador de evento (event handler) para un control, de modo que se ejecutar cuando ocurra un evento (en este caso, cuando se haya hecho clic sobre el botn). Haciendo clic sobre los tringulos de despliegue disponibles en el listado de objetos en el rea izquierda del editor de cdigo mostrar los eventos proporcionados para prcticamente cualquier cosa en la que puedas pensar (librerar el botn del ratn sobre el objeto, pulsar el botn del ratn sobre el objeto, el apuntador del ratn se est moviendo sobre el objeto, cualquier elemento soltado sobre el objeto, etc.) Utilizaremos varios de esto eventos en futuros proyectos. Nuevamente, existe multitud de documentacin sobre todos los eventos disponibles para cada tipo de control en la Referencia del Lenguaje incluida de serie. Un programa tambin consiste de objetos con propiedades La cadena (es decir las palabras) que queremos mostrar mediante el comando MsgBox debe obtenerse a partir de una propiedad del objeto de la ventana denomiando UserName (recuerdas cuando denimos el nombre del TextField?). En este caso el trmino propiedad tiene una similitud muy parecida a su signicado en el mundo real: es un atributo de algn objeto (en este caso, el texto introducido por el usuario en l). Para obtener el contenido de una propiedad en cualquier momento, debemos utilizar el nombre del objeto, un punto, y a continuacin el nombre de la propiedad en cuestin (todo ello sin espacios, tal y como en UserName.Text en nuestro programa). Cuando REALbasic ejecuta un comando y ve un argumento escrito de este modo, comprueba cul es el valor de la propiedad en ese momento y utiliza entonces dicho valor para completar el comando. No te preocupes si por el momento te parece algo confuso; en la siguiente leccin veremos con ms detalle cmo funciona una lnea de cdigo como esa. Entre bastidores: qu es un Compilador? Resulta til entender qu ocurre cuando haces clic sobre Ejecutar. Los ordenadores consisten en disposicione de millones y millones de transistores en circuitos muy completos. Dichos circuitos estn diseados de modo que entre las cosas que pueden hacer se incluyen tareas como almacenar y recuperar nmeros de forma muy rpida, as como tratar dichos nmeros no slo como informacin sino tambin como instrucciones simples para comparar otros nmeros, realizar clculos sobre dichos nmeros, moverlos de un lugar a otro, etc. Es posible indicar al ordenador (computador) que haga cualquier cosa de lo que es capaz utilizando estas simples instrucciones numricas (la creacin de programas de este tipo se denomina escribir cdigo mquina), pero esto resulta tremendamente ineciente y frustrante. No obstante, los programas escritos de este modo pueden ejecutarse con una velocidad tan rpida como de lo que sea capaz el propio ordenador. Cuando la velocidad es un factor importante, la gente escribir una pequea porcin del cdigo ms complejo de este modo: tal es as en partes de los juegos de ordenador, por ejemplo, y que se escriben de forma bastante habitual en cdigo mquina. Para que los humanos puedan escribir programas de ordenador de una forma ms eciente se han tomado dos vas principales. Ambas implican el uso de un lenguaje articial que proporciona un modo ms expresivo y amigable pare representar aquello que queremos que realice el ordenador. Representar el programa de este modo proporciona otra ventaja adicional: el programa est menos acoplado al lenguaje mquina de un tipo de ordenador en particular. Esto es lo que permite que puedas coger un programa de

REALbasic que funciona en Macitnosh y (utilizando la versin Professional o Studio de REALbasic) compilar ese mismo programa para que funcione sobre Microsoft Windows, con tan slo realizar algunos cambios mnimos o ningn cambio en absoluto. La diferencia entre las dos vas para afrontar el proceso reside en lo que el ordenador ha de lleva a cabo para hacer lo que indican estos comandos correspondientes al lenguaje de alto nivel: Un intrprete se limita a leer el cdigo y hacer aquello que indique el programa, mientras que Un compilador lee el cdigo del programa correspondiente al lenguaje de alto nivel y produce un programa en cdigo mquina que hace exctamente lo mismo. Cada una de estas opciones est destinada a propsitos distintos. Por varios motivos, los lenguajes de programacin interpretados tienden a ser un poco ms sencillos de escribir para los humanos, pero los programas ejecutados son considerablemente ms lentos en comparacin con los programas compilados. Los lenguajes de programacin compilados imponen por lo general algunas restricciones ms sobre el programador, con el objeto de que el compilador pueda producir un cdigo ms rpido. Los ordenadores modernos son tan rpidos que los ms sencillos lenguajes de programacin interpretados resultan mejores para tareas sencillas dado que facilitan al mximo la tarea de programacin. REALbasic es un compilador, pero el lenguaje de REALbasic es muy amigable, particularmente para un compilador. No obstante, existen algunas restricciones impuestas sobre t como programador para que el compilador de REALbasic pueda producir programas en cdigo mquina ms rpidos. En la prctica dichas restricciones no slo derivan en programas ms rpidos, sino que en los programas complejos, la mayora de estas restricciones tambin permiten encontrar errores lgicos. Una ltima anotacin Por ltimo: este curso es un curso sobre ciencias de la computacin en las que se utiliza REALbasic. Te ensea slo lo suciente sobre REALbasic para aprender ciencias de la computacin. Deberas leer ms sobre las caractersticas de REALbasic en la Gua del Usuario y en el resto de la documentacin. En particular, probablemente deberas de leer justo ahora el Captulo 2 de dicha gua, en la que se describe con ms detalle cmo funciona el IDE.

Leccin 2 Expresiones, Asignaciones y Tipos Objetivo En esta leccin aprenders cmo realizar clculos simples; cmo mover la informacin de un punto a otro y un poco sobre los diferentes tipos de datos de REALbasic. Un Saludo Mejorado Abre el proyecto de la Leccin 1. Vamos ha conseguir que sea capaz de hacer un mejor trabajo a la hora de saludar a alguien. 1 Abre Window1, y haz doble clic sobre el botn, de modo que REALbasic muestre de nuevo el manejador del evento Action correspondiente al botn. Aqu fue donde introdujimos el cdigo en nuestra ltima leccin. 2 Cambia el manejador del evento Action para que sea: MsgBox Hello + UserName.Text Ten en cuenta que hay un espacio despus de la coma, antes de la doble comilla. 3 Guarda el proyecto de nuevo, y ejectalo. Mucho mejor. Lo que hemos hecho ha sido proporcionar a REALbasic con una Expresin ms sosticada como argumento del comando MsgBox. Esta expresin aade algo de texto delante del texto obtenido mediante el campo UserName. Sobre las Expresiones Ya has visto expresiones en muchas ocasiones, en la clase de matemticas. Algo como esto: 3+4x5 es una expresin. Te indica varias cosas (aadir y multiplicar, en este caso), y proporciona toda la informacin que necesitas hacer sobre estos elementos (los nmeros que vas a aadir y multiplicar), y una vez que lo hayas hecho obtendrs el resultado. Hallar el resultado de una expresin se denomina evaluar la expresin. Todo esto tambin se aplica a las expresiones en los programas de ordenador, exceptuando que en este caso existen muchas ms operaciones disponibles en comparacin con las que puedes utilizar en matemticas, y que pueden operar sobre una variedad de elementos mucho mayor y no slo sobre nmeros (tal y como hemos podido ver en nuestro programa, donde se encuentra una expresin que contiene fragmentos de texto). De modo que este es el principio general: En cualquier parte de un programa de ordenador donde se espera que proporciones algn fragmento de informacin, dicho fragmento puede sustituirse por una expresin.

En realidad es un poco ms complicado que eso; esta es la versin completa: En cualquier parte de un programa de ordenador donde se espera que proporciones algn fragmento de informacin, dicho fragmento puede sustituirse por una expresin, siempre y cuando una vez que se evale dicha expresin su resultado sea del tipo correcto. Sobre los Tipos En un programa de ordenador cada fragmento de informacin se tiene un tipo. Esto es as porque slo puedes hacer una serie de cosas sobre ciertos tipos de informacin. Por ejemplo, no tiene sentido multiplicar dos cadenas de texto. Lo importante sobre un tipo es las operaciones que puedes realizar sobre algo de dicho tipo. Por ahora, slo necesitas saber que cualquier descripcin de un comando u operacin en la documentacin de REALbasic especicar de qu tipos deben ser los argumentos pasados o la operacin, y de qu tipo debera ser el resultado. REALbasic te mostrar un mensaje de error en el caso de que intentes ejecutar un programa que rompa estas reglas. (Una operacin es algo como + o * en matemticas. Otro ejemplo es el + en nuestro programa, que e encarga de concatenar dos cadenas de texto). En nuestro programa la expresin utiliza el smbolo + con el que ya ests familiarizado de las matemticas, pero en este caso no signica adicin (s signica adicin en el caso de que lo utilices con nmeros). Si incluyes cadenas de texto a ambos lados de dicho smbolo, cuando el ordenador evale esta expresin formar una nueva cadena en la que aadir la segunda cadena justo a continuacin de la primera (esto se conoce formalmente como concatenar las cadenas). Ten en cuenta que en la expresin de nuestro programa, hemos indicado a REALbasic qu parte de la lnea del programa era una cadena encerrndola entre comillas. Si no lo hacemos as, REALbasic intentar interpretar dicha parte de la lnea como si fuera un comando y producir un error cuando intentes ejecutar el programa (veremos qu ocurre cuando hagas esto dentro de un momento). Es importante entender que los espacios son caracteres tal y como las letras y los nmeros. En nuestro ejemplo, hemos puesto un espacio detrs de la coma, dentro de las dobles comillas, porque si no lo hubisemos hecho as el ordenador habra sido muy obediente y producira un resultado como este: Hola,Chico En vez de Hola, Chico Experimento Prueba a experimentar con la expresin. Por ejemplo, puedes crear una sentencia ms larga. Cmo haras que el ordenador produjese un resultado como este? (pista: puedes usar el operador + ms de una vez dentro de la misma expresin). Hola, Chico. Qu tal ests?

Un Error Veamos qu ocurre si introducimos de forma deliberada un error en nuestro programa. Cambia el cdigo para que sea as: MsgBox Hola, + UserName.Text + 2 Cuando intentes ejecutar esto, REALbasic pondr un bug a la izquierda de la lnea problemtica y mostrar un mensaje en la parte inferior de la ventana. Figura 14. El Editor de Cdigo, mostrando un error del compilador. (Captura Figura 14) Un error de tipo es cuando no puedes realizar la operacin que has indicado sobre los tipos de elementos proporcionados. En este caso, REALbasic espera que si ests aadiendo un nmero a algo, entonces dicho elemento debera ser tambin un nmero. Y si ests aadiendo una cadena a un elemento, entonces debera ser una cadena. Si quisieras concatenar un 2 a la cadena, entonces deberas de incluirlo entre comillas, as: MsgBox Hola, + UserName.Text + 2 Nuevamente, las comillas indican a REALbasic que el elemento interno es una cadena. Por cierto, has advertido que a medida que has estado trabajando con REALbasic, cada vez que apuntabas cualquier elemento con el apuntador, la lnea situada en la parte inferior de la ventana proporcionaba informacin til sobre dicho elemento? Otro ejemplo Intentemos un ejemplo ms complicado. Crearemos un programa que sumar varios nmeros: 1 Selecciona Nuevo Proyecto en el men Archivo. 2 Abre el Editor de Ventana correspondiente a Window1, arrastra tres controles TextField, una lnea y un PushButton sobre la ventana. Ordnalos y ajusta el texto del botn para que la ventana tenga el siguiente aspecto: Figura 15. Arrastra tres TextFields, una lnea y un PushButton en la Window1. (Captura Figura 15) Es buena idea proporcionar nombres identicativos a cado uno de los objetos imporantes del programa. Puedes denir el nombre haciendo clic sobre el objeto para cambiar a continuacin el campo Name: en el panel de Propiedades. De arriba hacia abajo, utiliza los siguientes nombres para los TextFields: Source1, Source2 y Result. Cambia el nombre del PushButton a EvaluateButton. 3 Haz doble clic en el PushButton y congura su manejador Action como: Result.text = Str(CDbl(Source1.text) + CDbl(Source2.text))

No te olvides de guardar el proyecto en este momento. Lo utilizaremos de nuevo en la siguiente leccin. Para comprender la expresin necesitas conocer algunas cosas: Adems de las operaciones y de los comandos que hemos visto hasta aora, REALbasic tiene funciones. Cuando se evala, una funcin proporciona un valor de algn tipo, como por ejemplo una cadena o un nmero. Las funciones estn escritas como un nombre seguido por una serie de argumentos entre parntesis. CDbl es una funcin con n nico argumento de cadena, y devuelve dicha cadena convertida en un nmero. Del mismo modo, Str tiene un nico argumento que es un nmero, y devuelve dicho nmero como cadena. Dado que puedes utilizar una expresin en cualquier parte en la que se espera algn tipo de informacin, entonces tambin puedes incluir una expresin dentro de otra expresin. El ordenador evaluar dicha expresin de dentro hacia afuera. Esto puede sonar algo intimidatorio, pero es algo que probablemente ya te resulte familiar. Una expresin numricoa como 3 * (4 + 5) est formada por la expresin (4 + 5) dentro de una expresin ms larga, y esto funciona exactamente del mismo modo en REALbasic, donde puedes utilizar los parntesis para controlar el orden en el que se evalan los elementos. Ahora ya tenemos suciente informacin para comprender qu signican las anteriores expresiones. Vemoslas desde dentro hacia afuera: Expresin(es) Source1.text y Source2.text CDbl(Source1.text) y CDbl(Source2.text) Signicado El contenido que se haya escrito en los dos campos superiores de Window1. El valor numrico de lo que se haya escrito en los campos (este ser 0 si lo que se haya escrito no puede ser interpretado como nmero). Aadir los nmeros de ambos campos. Convertir el resultado de nuevo en cadena.

CDbl(Source1.text) + CDbl(Source2.text) Str(CDbl(Source1.text) + CDbl(Source2.text))

Advierte cmo hemos tenido que asegurarnos sobre el tipo de lo que se suministra en cada uno de los pasos: Los TextFields contienen cadenas, de modo que tenemos que convertirlos en nmero de modo que podamos sumarlos (2 no es lo mismo que 2, dado que 2 + 2 = 4, mientras que 2 + 2 = 22). A continuacin hemos convertido el resultado de nuevo en una cadena, dado que el comando MsgBox no acepta un nmero. Ms Errores Incluso los profesionales cometen errores; aqu puedes ver algunos errores que puedes introducir de forma accidental, el mensaje mostrado por REALbasic cuando intentas ejecutar el programa y la explicacin del error:

Cdigo MsgBox Username.

Mensaje de Error Error: Los parmetros no son compatibles con esta funcin

Explicacin El argumento del comando, funcin u operador es del tipo errneo; en este caso, Username es un TextField, y no puedes mostrar un TextField tienes que mostrar su propiedad de texto: Username.text Has olvidado el + Has olvidado el punto entre Username y text. Esto funciona, pero muestra Hola, + Username. Esto muestra la importancia de poner las comillas en el sitio correcto.

MsgBox hola, Username.text MsgBox hola, + Usernametext MsgBox Hola, + Username

Error de Sintaxis Error: Este mtodo o propiedad no existe No hay error

Experimento Prueba a cambiar el proyecto para que multiplique dos nmeros. El smbolo de la multiplicacin en REALbasic es * (de modo que podemos escribir un cuatro como 2 * 2). Tambin puedes hacer la divisin con el smbolo /. La resta es el smbolo que ya conoces. Si ya lo has probado, comrpueba si el programa funciona con nmeros con parte decimal o con nmeros negativos. Qu ocurre si conviertes el proyecto para que haga divisiones y la pides que divida entre cero?

Leccin 3 Condicionales y el Depurador Objetivo En esta leccin aprenders cmo programar REALbasic para tomar decisiones sencillas, y cmo utilizar el depurador de modo que puedas comprobar la ejecucin del cdigo en REALbasic lnea a lnea. Una ampliacin simple sobre el programa anterior Pongmonos directamente en ello. 1 Abre el programa que hemos guardado en el segundo ejemplo de la leccin anterior. 2 Como antes, con el Editor del Proyecto delante, abre el Editor de Ventana correspondiente a Window1 y ampla su listado de eventos en el navegador correspondiente al Editor de Cdigo, de modo que podamos acceder a su manejador de evento Action. 3 Cambia el manejador de evento por esto: If Source1.text = salir then Beep Quit Else Result.text = Source1.text + Source2.text End if 4 Ejecuta la aplicacin. Escribe varias cosas y pulsa el botn, a continuacin prueba a escribir salir en el campo superior. Aqu encontramos un par de comandos nuevos (beep y quit), cuyos efectos deberan ser obvios. Lo interesante aqu es la construccin If-Then-Else-End If que nos proporciona el comportamiento especial cuando hayas introducido la palabra salir. Veremos con ms detalle la construccin If-Then-Else-End If a continuacin. Por ahora, vamos a utilizar el depurador de REALbasic para observar la ejecucin del cdigo. 5 Haz clic en la lnea gris situada a la izquierda de la primera lnea (el comando if). Advierte que se crea un punto de color rojo en dicha lnea. 6 Ejecuta el programa, escribe algo en los campos y haz clic sobre el botn. REALbasic ejecutar automticamente el programa pero tan pronto como vaya a ejecutar la lnea sobre la que hemos incluido el punto de parada, se encargar de traer el ID de REALbasic a primer plano, cambiar a la pestaa Ejecutar y mostrando dicha lnea resaltada para indicarnos que est a punto de ejecutarla: Figura 16. El depurador de REALbasic. (Captura Figura 16)

Tambin vers el panel Variables (as como un men desplegable del que no nos ocuparemos por el momento): Figura 17. El panel de Variables. (Captura Figura 17) El panel Variables muestra toda la informacin que est disponible para dicha parte del programa. Por motivos que abordaremos en una leccin posterior, Self se reere a la ventana, mientras que Me se reere al objeto para el que se est ejecutando el cdigo (es decir, el PushButton). De modo que si haces clic sobre cualquiera de estos enlaces, REALbasic cambiar el panel de variables para mostrar las propiedades actuales de la ventana o del botn: Figura 18. El panel de Visor de Objeto para el PushButton. (Captura Figura 18) El men desplegable situado sobre el panel de variables te indica de qu objeto ests viendo las propiedades en ese momento. Si accedes a dicho men te permitir regresar para ver las propiedades de las que partiste (dado que las propiedades pueden ser objetos que, a su vez, tambin contienen propiedades, puedes navegar por unas cuantas capas de objetos; el men te permite regresar hacia el punto original). Veremos ms detenidamente cmo usar dichas caractersticas en siguientes lecciones, pero por ahora veremos cmo podemos ir paso a paso a travs del cdigo. 7 Haz clic sobre el botn Paso en la barra de herramientas del Depurador. Ahora aparecer destacada la siguiente lnea que se vaya a ejecutar (la lnea depender de lo que hayas escrito en los TextFields en el programa en ejecucin). En este programa, no existe ninguna diferencia entre Paso y Paso Dentro. Cualquiera de estos dos comandos avanzar una lnea cada vez a lo largo del programa en ejecucin. Tambin puedes Detener el programa en ejecucin o bien seleccionar Reanudar, en cuyo caso se saldr del depurador y se continuar la ejecucin del programa normalmente (hasta que el programa encuentre nuevamente una lnea con un punto de parada asignado). Tambin puedes aadir y eliminar puntos de parada desde el depurador haciendo clic sobre cualquiera de los guiones situados en el margen izquierdo del cdigo. Si una lnea de cdigo no tiene un guin a su izquierda entonces no puedes incluir un punto de parada sobre ella. Puedes cambiar entre REALbasic y el programa en ejecucin en cualquier momento, aunque si el programa est detenido en el depurador entonces comprobars que no es tan gil cuando cambies de nuevo a l. Asegrate de usar el depurador a discreccin a lo largo de nuestras lecciones, de modo que puedas ver lo que est ocurriendo en cada momento. Un + ms inteligente No hemos terminado an con el If-Then. Veamos un ejemplo ms completo.

Dado que el + puede funcionar tanto con cadenas como con nmeros, hagamos que nuestro proyecto se encargue de hacer cada una de estas operaciones automticamente: si lo que se ha introducido en cada campo es un nmero los sumaremos, si no concatenaremos las dos cadenas (la concatenacin es el nombre de lo que hace el smbolo + sobre dos cadenas). 1 Cambia el manejador del evento a esto: If (CDbl(Source1.text) = 0 and Source1.text<>0) or_ (CDbl(Source2.text) = 0 and Source2.text <>0) then Result.text = Source1.text + Source2.text Else Result.text = Str(CDbl(Source1.text) + CDbl(Source2.text)) End if Nuevamente, estamos interesados en la estructura if-then para la toma de decisiones, y que en su forma completa tiene el siguiente aspecto: If ... Then ... Else ... End If Tal y como se indica aqu con los puntos suspensivos (...), existen tres lugares donde puedes introducir expresiones y comandos de REALbasic. Para completar un If-Then en REALbasic: En la primera lnea, entre el Ify el Then se encuentra una expresin Booleana (profundizaremos sobre esto ms adelante); Despus de dicha lnea, puedes tener tantas lneas como desees de comandos REALbasic; Si lo deseas, puedes tener una lnea con la palabra Else, seguida de otros comandos REALbasic adicionales. Y todo ello naliza con End If. Expresiones Booleanas En las anteriores lecciones hemos visto las expresiones de cadenay las expresiones numricas. Las expresiones Booleanas son muy similares, excepto que las expresiones Booleanas slo contemplan los valores True (verdadero) y False (Falso). True y False son valores que se pueden manipular con REALbasic, tal y como ocurre con los nmeros y las cadenas. Hay dos tipos de expresiones Booleanas. La lgica Booleana fue inventada por George Boole (1815-1864), y fue presentada por primera vez en An Investigation of the Laws of Thought (1854). Es un sistema muy simple, y cualquier programador de ordenadores debera estudiar sus fundamentos:

Simple: Las expresiones Booleanas comparan algo con otro valor en el programa, generalmente utilizando operaciones como = (igual), <> (no igual), <= (menor o igual que), o bien >= (mayor o igual que). En algunos casos una propiedad o bien algn otro elemento del programa ser simplemente un valor Booleano. Las cajas de vericacin que ves en la paleta de propiedades cuando haces clic sobre un control suponen un buen ejemplo. Source1.Bold es una expresin Booleana vlida, dado que existe una caja de vercacin Bold en la paleta Propiedades cuando haces clic sobre uno de los TextFields; de modo que la expresin Source1.Bold se evaluara a True cuando la caja de vericacin correspondiente a Bold est activada; y Compuesta: Las expresiones Booleanas estn formadas a partir de otras expresiones Booleanas (que a su vez pueden ser simples o compuestas), utilizando los Operadores Booleanos Not (no), And (y) u Or (o). Tal y como ocurre con los otros tipos de expresiones, necesitars utilizar con frecuencia parntesis en las expresiones Booleanas para aclarar en qu orden deben realizarse las operaciones. De igual modo, tal y como ocurre con expresiones de otro tipo, REALbasic halla el valor nal desde dentro hacia afuera. Vemos cmo hace REALbasic para evaluar la expresin en nuestro programa: (CDbl(Source1.text) = 0 and Source1.text <> 0) Or (CDbl(Source2.text) = 0 and Source2.text <> 0) Expresin(es) Source1.text CDbl(Source1.text) CDbl(Source1.text) = 0 Source1.text <> 0 Signicado Los contenidos de Source1. El valor numrico de Source1.text si es un nmero, o bien 0 de lo contrario. Cierto (true) si Source1.text se evala como 0; falso (false) de lo contrario. Cierto (true) si Source1.text es algo distinto de 0 (ten en cuenta que <> signica no es igual a). Cierto (true) si CDbl(Source1.text) se evala como 0, cuando el texto en Source1 no es 0. En otras palabras, True si el usuario ha introducido algo que no es un nmero (recuerda: algo que no es un nmero proporcionado como argumento de CDbl se evala como 0). Ten en cuetna que el And entre las dos expresiones se evala como True (cierto) si ambas expresiones a ambos lados son ciertas. Lo mismo, slo que en este caso aplicado a lo que se haya introducido en Source2.

(CDbl(Source1.text) = 0 And Source1.Text <> 0)

(CDbl(Source2.text) = 0 and Source2.text <> 0)

Expresin(es) (CDbl(Source1.text) = 0 and Source1.text <> 0) Or (CDbl(Source2.text) = 0 and Source2.text <> 0)

Signicado Cierto (true) si tanto Source1 o Source2 tienen un valor distinto de un nmero.

Advierte el uso de los parntesis para aclarar el orden de las operaciones. Existen reglas sobre el modo en el que REALbasic evala las expresiones en el caso de que no se usen los parntesis: CDbl(Source1.text) = 0 and Source1.text <> 0 Or CDbl(Source2.text) = 0 and Source2.text <> 0 Pero es mucho ms simple y claro usar los parntesis. Puedes encontrar ms til echar un vistazo al modo en el que se evala esta expresin usando un tipo de diagrama denominado rbol de sintxis: Figura 10. rbol de sintxis. (Captura Figura 19) REALbasic evala la expresin desde la parte inferior del rbol de sintxis hacia arriba. En la parte inferior de cada lnea en el diagrama hay una expresin Booleana que proporciona un resultado Booleano, y en la parte superior de dicha lnea se encuentra un operador Booleano que combina estos valores Booleanos, formando una expresin Booleana ms extensa. De modo que ahora puedes ver como funciona toda la construccin if-then-else en nuestro cdigo. Si el usuario no introduce nmeros en ambos campos, entonces REALbasic concatena las cadenas: Result.text = Source1.text + Source2.text De lo contrario, el orenador suma los valores introducidos en los campos (la parte que sigue al Else): Result.text = Str(CDbl(Source1.text) + CDbl(Source2.text)) Por cierto, el otro operador Booleano del que no hemos hablado, Not, es muy sencillo de usar: Cuando pones Not delante de un valor Booleano x, entonces la expresin Not se convierte en True si x es False, y se evala como False en el caso de que x sea True. De modo que una expresin equivalente para nuestro manejador de evento podra ser: If Not((CDbl(Source1.text) = 0 and Source1.text <> 0) or_ (CDbl(Source2.text) = 0 and Source2.text<>0)) then Result.text = Str(CDbl(Source1.text) + CDbl(Source2.text)) Else Result.text = Source1.text + Source2.text

End if Aqu hemos hecho algunas cosas: Hemos aplicado el operador Not a toda la expresin esntre el If y el Then. Ten enc uenta que hemos encerrado toda la expresin entre parntesis, de modo que el Not se aplique a los resultados de toda la expresin en vez de hacerlo slo sobre la primera parte de ella; y Hemos intercambiado los comandos entre el Then y el Else con aquellos entre el Else y el End If. Por ltimo, necesitas saber que el Else que forma parte de un If-Then es opcional. De modo que podemos sumar slo los nmeros e ignorar el resto con este cdigo: If Not((CDbl(Source1.text) = 0 and Source1.text<>0) or_ (CDbl(Source2.text) = 0 and Source2.text<>0)) then Result.text = Str(CDbl(Source1.text) + CDbl(Source2.text)) End if End Sub ElseIf Si necesitas crear una secuencia de decisiones, entonces puedes poner varias instrucciones if-then dentro de otras instrucciones if-then, como aqu: If (CDbl(Source1.text) = 0 and Source1.text<>0) or_ (CDbl(Source2.text) = 0 and Source2.text <> 0) then Result.text = Source1.text + Source2.text Else If Result.text = salir then Quit Else Result.text = Str(CDbl(Source1.text) + CDbl(Source2.text)) End if End if End sub Esto es perfectamente legtimo y funcionar tal y como puedes esperar. Sin embargo, si necesitas crear una secuencia como esta, ten en cuenta que resultar algo difcil de leer y se indentar excesivamente hacia la derecha. REALbasic proporciona un modo diferente de decir lo mismo, utilizando para ello el comando ElseIf donde se desplaza el prximo If a la misma lnea en la que se encuentra el Else, y donde slo se requiere un EndIf al nal. En otras palabras, el cdigo anterior podra escribirse del siguiente modo: If (CDbl(Source1.text) = 0 and Source1.text <> 0) or_ (CDbl(Source2.text) = 0 and Source2.text <> 0) then Result.text = Source1.text + Source2.text Elseif Result.text = salir then Quit Else Result.text = Str(CDbl(Source1.text) + CDbl(Source2.text))

End if End Sub REALbasic ejecuta la primera parte If o Elseif cuya expresin Booleana se evale como True (cierto) y salta el resto. Experimento Asegrate de que entiendes cmo crear diferentes tipos de expresiones Booleanas y no te asustes de usar parntesis para controlar el orden en el que REALbasic debe evaluar dichas expresiones. Un par de cosas que puedes probar son: Haz que el programa emita un beep y que muestre un mensaje de error en el caso de que el usuario escriba un nmero negativo, o bien que concatene lo que haya introducido en el caso contrario: Haz que el programa salga en el caso de que el usuario escriba salir en ambos campos, pero suma los valores en el caso contrario.

Leccin 4 Variables y Bucles Objetivo En esta leccin aprenderemos a alamacenar informacin y repetir acciones. Variables Para poder hacer algo una cantidad determinada de veces, necesitamos un modo de realizar un segumiento del contador a medida que lo llevamos a cabo. Este contador ser un nmero completo, o entero en trminos matemticos. El elemento en el que mantenemos esta informacin se denomina variable. Piensa en ello como en un fragmento de papel sobre el que podemos escribir informacin. El fragmento de papel tiene un nombre de modo que podemos referirnos a l. Cuando utilizamos el nombre de una variable en una expresin, REALbasic evala el nombre para obtener la informacin contenida en la variable con dicho nombre en ese momento. Repetir un Beep Vamos a crear un nuevo proyecto que repetir una accin durante una cantidad determinada de veces. 1 Crea un nuevo proyecto y abre Window1 en su Editor de Ventana de modo que podamos crear su interfaz de usuario. 2 Arrastra una etiqueta, un PushButton y un Slider en la ventana, y congralo de modo que tenga el mismo aspecto que puede verse en la Figura 20: Figura 20. La interfaz de usuario para el proyecto. (Captura Figura 20) 3 Haz clic en el Slider en la Window1. En el panel de Propiedades congura la propiedades para el estado inicial del Slider con los siguientes valores: Propiedad Minimum Value Maximum 1 0 10 Valor

4 Haz doble clic sobre el PushButton y congura su handler Action as: Dim counter as Integer For counter = 1 to slider1.Value Beep Next Si ests haciendo esto sobre Mac OSX entonces sonarn varios beeps al mismo tiempo, de modo que cmbialo para que sea:

Dim counter as Integer For counter = 1 to slider1.Value MsgBox Beep Next 5 Ejecuta el proyecto, haz clic en el botn, mueve el slider y haz clic de nuevo en el botn. Si lo deseas, consulta la ayuda incorporada para saber s sobre el control Slider. Dim En una leccin anterior mencionamos que REALbasic es un lenguaje de programacin compilado, y que esto ocasionalmente signica que tenemos que hacer una serie de cosas para que el programa resultante funcione ms rpido (estas cosas tambin nos permiten detectar nuestros propios errores de programacin). Una de las cosas que tenemos que declarar a REALbasic es de qu tipo es la informacin que contendr una variable. Si intentamos asignar el tipo de informacin errneo a dicha variable, entonces REALbasic producir un error. Sobre esto existe una excepcin: existe un tipo de variable denominado variant y que contiene cualquier tipo de dato que puede almacenar REALbasic. Su funcin es principalmente la de facilitar el uso de cdigo escrito para Visual Basic de Microsoft. REALbasic ha sido diseado para que sea similar a Visual Basic, y sorprendentemente algunos proyectos complejos de Visual Basic se pueden convertir a REALbasic realizando slo unos mnimos cambios. El otro uso de las variantes es si estamos escribiendo cdigo rpido sin importar lo rpido que se ejecute. Si slo necesitas automatizar una tarea sencilla sin ms, entonces el uso de las variantes simplica almacenar la informacin. Las variantes hacen que el cdigo corra ms lento, y pueden ocultar errores de programacin, pero en los proyectos simples esto no suele representar un problema. En el resto de los casos, es preferible evitar el uso de las variantes como si se tratasae de una plaga. Si pudisemos utilizar cualquier tipo de variable para almacenar cualquier tipo de informacin, entonces cada vez que REALbasic quisiera utilizar un valor que hubisemos almacenado en una variable tendra que comprobar qu tipo de informacin contiene esa variable, y eso lo ralentizara todo. Declarar el tipo es un contrato entre t y REALbasic: tu prometes no incluir el tipo de informacin incorrecto en dicha variable, y REALbasic puede conar en ello para hacer que el cdigo funcione con mayor velocidad. El comadno para ello se denomina Dim por razones histricas: REALbasic est basado en un antiguo lenguaje de programacin denominado BASIC (abreviatura de Beginners AllPurposse Symbolic Instruction Code). REALbasic es mucho ms avanzado que el antiguo lenguaje BASIC, pero comparte el objetivo de su diseo en hacer que las cosas resulten ms sencillas para los profanos. Tambin soporta los principales comandos qu hicieron de BASIC lo que es. De igual modo, la mayora del antiguo cdigo BASIC funcionar con unas simples modicaciones en REALbasic.

Uno de estos viejos comandos era dim, abreviatura de dimension. En dichos lenguajes de programacin antuguos, dim estaba reservado para declarar arreglos (veremos los arreglos en lecciones posteriores), para lo cual el nombre del comando tena sentido. De modo que el nombre es un poco extrao ahora porque ha evolucionado a partir de un sentido menos amplio. Puedes utilizar Dim en tantas variables de tu cdigo como deses, utilizando para ello diferentes comandos Dim. Puedes declarar una variable en cualquier parte del cdigo que desees, pero ten en cuenta que slo podrs utilizarla a partir del punto en el que hayas declarado la variable y que si la declaras dentro de un bucle entonces slo podrs utilizarla dentro de dicho bucle (esto resulta til, dado que slo necesitas una variable con un pequeo fragmento de cdigo, puedes hacer que cobre vida automticamente y que sea eliminada una vez que se haya completado). For... Next El otro elemento nuevo en nuestro cdigo es el bucle For... Next y que se encarga de reptir una accin. Un bucle For tiene la siguiente estructura bsica: Una lnea que empieza con For, seguida por un nombre de variable, un signo de igual (=), un valor inicial, la palabra to y un valor nal. Tantos comandos REALbasic como desees, cada uno de ellos en su propia lnea (denominado el cuerpo del bucle); y. La palabra Next en su propia lnea. En nuestro ejemplo (For counter = 1 to Slider1.value), la variable se llama Counter, el valor inicial es 1 y el valor nal es la propiedad Value del Slider1. Cuando REALbasic encuentra un bucle For-Next dene la variable con el valor inicial, a continuacin comprueba de forma repetida si la variable es mayor que el valor nal y, hasta que as sea, ejecutar el cdigo del cuerpo del bucle aadiendo 1 al valor de la variable. Si buscas en la Referencia del Lenguaje incorporada, vers que puedes aadir el comando Step al nal de la lnea For de modo que le permita aadir a la variable un valor distinto de 1 en cada una de las vueltas de ejecucin. Tambin existe la palabra reservada DownTo para contar hacia atrs. En este caso no necesitamos hacer nada de esto, pero eres libre de usar el valor de la variable dentro del cuerpo del bucle en cuaqluier punto donde necesites un valor numrico. Tambin puedes limitarte a cambiar slo el valor de la variable, quiz para hacer que el bucle nalice con anterioridad. Veremos en un momento cmo acceder y cambiar el valor de una variable. Por ltimo, ten en cuenta que la variable debe ser de tipo numrico (integer es el nico tipo numrico que hemos visto hasta el momento, y de hecho es la variable de tipo ms comn para controlar los bucles). Repetir una Cadena Probemos algo un poco ms complejo:

1 Cambia Window1 para que tenga el aspecto mostrado en la Figura 21: Figura 21. Window1 en el segundo proyecto. (Captura Figura 21) Recuerda: para cambiar el nombre de un control, haz clic sobre l y edita su nombre en el panel de Propiedades. En este caso, el TextField pequeo tiene el nombre SourceString y el control TextArea de mayor tamao se llama ResultString. Del mismo modo, activa la casilla de vericacin Multiline correspondiente a ResultStringen el panel de Propiedades. El slider tiene los mismos ajuses que en el ejemplo anterior. 2 Introduce el siguiente cdigo en el manejador de evento Action correspondiente al PushButton: Dim store as String For counter as Integer = 1 to slider1.Value Store = Store + SourceString.text Next ResultString.text = Store La instruccin Dim crea una variable de cadena de modo que tengamos un lugar en el que crear una nueva cadena. La variable Counter utilizada en el bucle For est declarada como Integer (entero) dentro de la instruccin For. Dentro del bucle For se encuentra un nico comando, store = store + SourceString.text Este es un comando de asignacin. Se escribe con el nombre de una variable o propiedad, un signo igual (=) y a continuacin la expresin. El resultado de la expresin debe ser del mismo tipo que la variable o propiedad situada a la izquierda del signo igual. Ten en cuenta que en este caso la variable tambin forma parte de la expresin. Esto es importante de modo que conviene remarcarlo: La parte derecha de una asignacin se evala por completo y, entonces, se asigna su resultado a la variable o propiedad situada a la izquierda. De modo que en este caso, tomamos la cadena actual de la variable store, ponemos el texto del TextField SourceString tras ella, y volvemos a poner el resultado de nuevo en la variable store. En otras palabras, aadimos el texto del TextField SourceString al nal de store. Y hacemos esta operacin tantas veces como indique el valor actual del slider (dado que este es el valor que utilizamos para el bucle For). Dado que cuando creamos una varibale esta tiene un tipo de valor vaco (las cadenas no tienen carecteres y las numricas tienen 0 como valor), lo que obtenemos es una

determinada cantidad de copias de la cadena que se haya introducido en el TextField SourceString. Ejecuta el cdigo, de modo que puedas comprobar que esto es lo que de hecho ocurre. No te olvides de escribir algo en el campo superior antes de que hagas clic en el botn. Un par de mejoras sencillas Este no es realmente el objeto de esta leccin, pero resulta tan sencillo de hacer que es difcil resistirse: 1 Copia el cdigo del manejado de evento Action del PushButton e introdcelo en el manejado de evento ValueChanged del Slider. 2 Ejecuta el programa de nuevo. En esta ocasin no tendrs que utilizar el botn. De hecho puedes volver al editor de ventana, seleccionarlo y pulsar la tecla Borrar para eliminarlo. 3 Ahora dirgete de nuevo a la ventana, haz clic sobre el slider y activa su propiedad LiveScroll, y vuelve a probar de nuevo el programa. Esto cambia el modo en el que el slider llama a su manejador de evento. Antes, se ejecutaba el manejador de evento cada vez que soltabas el botn del ratn; pero con la propiedad LiveScroll ajustada a True, el manejador de evento se ejecuta a medida que mueves el slider. Es ms satisfactorio, aunque si el manejador requiere mucho tiempo para ejecutarse puede resultar algo lento, de modo que debes decidir cuando utilizar esta caracterstica. Experimento Hay unas cuantas cosas que puedes hacer a partir de aqu, combinando las cosas que hemos aprendido hasta ahora: Crea un programa que haga lo mismo que este ltimo, salvo que escribas la palabra beep en el TextField SourceString. En ese caso, emitir un beep tantas veces como indice el slider. Haz un programa que tenga un slider y un TextField, y que muestre el valor numrico del slider en el TextField. Ten en cuenta que puedes activar la propiedad ReadOnly de un TextField para impedir que el usuario puede introducir datos en l. Crea un programa con un botn y un slider, donde el slider haga que el botn se mueva por la ventana. (Esto es sorprendentemente sencillo: mediante cdigo puedes modicar cualquier cosa que veas en en la paleta Propiedades, asignando para ello un valor a una propiedad del botn usando el mismo nombre que veas en la paleta. Si haces clic en el control PushButton, vers que tiene una propiedad Left. Todo lo que necesitas decir es algo como: PushButton1.Left = Slider1.Value * 5 Echa un vistazo al resto de propiedades de los otros controles. Puedes hacer todo tipo de cosas divertidas y sorprendentes cambindolas.

Leccin 5 Mdulos, Mtodos y Recursin Objetivo En esta leccin aprenderemos los fundamentes sobre el uso de Mdulos, Mtodos y de la Recursin. Los Mdulos y los Mtodos son formas de dividir un proyecto complejo en partes ms manejables. Los Mtodos tambin nos permiten reutilizar cdigo de una forma especial. La Recursin es un modo de repetir las acciones dentro de un programa. Repetir una Cadena Vamos a crear un proyecto que repita una cadena una cantidad determinada de veces. 1 Ejecuta REALbasic, en el caso de que no est ya en funcionamiento. Si ya est funcionando, selecciona Nuevo Proyecto en el men Archivo. Ahora deberas de tener un nuevo proyecto. 2 Haz clic sobre el botn Aadir Mdulo en el Editor de Proyecto. Un mdulo es un lugar en el que puedes almacenar variables y cdigo de programa que puedes utilizar desde cualquier parte del programa. 3 Cambia el nombre del mdulo en el panel de Propiedades a StringLibrary. Siempre que ests poniendo un nombre a algo en REALbasic recuerda que no puedes incluir espacios como parte del nombre. 4 Haz doble clic sobre el mdulo para abrirlo en el editor de la ventana y haz clic sobre el botn Aadir Mtodo. REALbasic mostrar un Editor de Cdigo en el que puedes incluir la informacin sobre el mtodo. Figura 22. El Editor de Mtodo. (captura Figura 22) Un mtodo debe de tener un Nombre de Mtodo. Tambin puedes proporcionar una lista de argumentos para el motdo utilizando para ello el campo Parmetros (parmetros es equivalente a argumentos). En el caso de que haya ms de un argumento, debes separar los argumentos mediante comas. La denicin de cada argumento usa exactamente la misma forma que utilizaras con un comando Dim. En este caso, el mtodo tiene dos argumentos: el primero es una string llamada s, y el segundo es un integer llamado n. Por ltimo, puedes vonvertir el mtodo en una funcin declarando un nico Tipo Devuelto. En este caso, el mtodo es una funcin que devuelve una String. Como vers dentro de un momento, en REALbasic las funciones son exactamente como funciones en matemticas: tienen un Dominio (el conjunto de posibles argumentos para la funcin; en este caso, el conjunto de pares de cadenas y los valores enteros) y un Rango (el conjunto de posibles resultados; en este caso, el conjunto de todas las cadenas).

Una vez hayas creado un mtodo o una funcin en un Mdulo como este, puedes llamarlo tal y como llamas cualquiera de los mtodos o funciones incorporados de serie como por ejemplo la funcin CDbl que hemos utilizado en las lecciones anteriores. 5 Nombra la funcin como RepeatString y proporcinale como parametros s as String y n as Integer. Dene el Tipo Devuelto como String. 6 Una vez hayas declarado el nuevo mtodo, introduce el siguiente cdigo: Dim resultText as String Dim counter as Integer For counter = 1 to n resultText = resultText + s + EndOfLine next Return resultText Esto es similar al otro cdigo que hemos visto antes, excepto por el comando return, y que se encarga de nalizar el mtodo y devolver un valor a la expresin o funcin de origen. La ventana del editor de cdigo debera tener el siguiente aspecto. Figura 23. La funcin RepeatString. (Captura Figura 23) El tipo de dato que hemos usado como Tipo Devuelto en la declaracin debe coincidir con el tipo de dato de la variable result. 7 Abre la ventana Window1 y aade dos TextFields y un slider como el de la Figura 24. Figura 24. La ventana de String Repeater. (Captura Figura 24) 8 Dene los nombres de los objetos, de arriba a abjo, como: Source, Repetitions y Result. Congura las otras propiedades como: Control Source Repetitions Result Propiedades Width = 224, Height = 22 Width = 224, Height = 16, Minimum = 0, Value = 0, Maximum = 100 Width = 224, Height = 182, Multiline = True (activado)

As como podemos aadir mtodos a los mdulos, tambin podemos aadir mtodos a los objetos en nuestros programas. En este caso vamos a aadir un mtodo a la ventana. 9 Cambia al Editor de Cdigo de Window1 y haz clic en el botn Aadir Mtodo en la barra de herramientas correspondiente al Editor de Cdigo. Nombra el Mtodo Update y deja vacos tanto sus parmetros como el Tipo Devuelto. Advierte que el nuevo Mtodo aparece listado en el grupo Mtodos del panel izquierdo en la ventana. Figura 25. El Editor de Cdigo mostrando el mtodo Update de Window1. (captura Figura 25) 10 Introduce el siguiente cdigo: Result.text = RepeatString(Source.text, Repetitions.Value) Advierte que no hay espacios a ambos lados de los puntos. El Editor de Cdigo debera tener el mismo aspecto que el mostrado por la Figura 25. 11 Expande el item Controles en el navegador y expande a continuacin el elemento Repetitions. Introduce el siguiente cdigo en el manejador de evento ValueChanged correspondiente a Repetitions: Update Esto llama al mtodo Update de la ventana cada vez que se cambia el valor del slider. Es decir, cada vez que el usuario mueve el slider hacia la izquierda o hacia la derecha. 12 Ejecuta el programa, escribe algo en el TextField superior y mueve el slider. 13 Sita un punto de parada en el manejado de evento ValueChanged, y ejecuta el programa de nuevo. 14 Al hacer clic sobre el botn Paso, sigue la ejecucin del programa por el manejador del evento, encargado de llamar a Update y que a su vez llama a RepeatString. Advierte que cada mtodo regresa de nuevo al mtodo desde el que fue invocado. Es posible que tambin quieras examinar el men desplegable situado sobre el cdigo en el depurador, lo que te permite ver en orden los mtodos de los que aun no has salido. Si seleccionas uno de estos mtodos, el depurador cambiar para mostrar el cdigo correspondiente a dicho mtodo, la lnea que se est ejecutando en ese caso y tambin las variables para dicho mtodo. Probableme encuentres de utilidad el botn Paso Fuera. Dicho botn naliza la ejecucin del mtodo actual y reactiva a continuacin el depurador tan pronto como regrese al mtodo desde el que se ha llamado. El comando Saltar tambin es de utilidad: ejecuta un

mtodo sin recorrer su cdigo, y reanuda la depuracin en la lnea siguiente a la llamada del mtodo. Cmo ejecuta REALbasic un Mtodo o Funcin Es importante comprender qu ocurre cuando REALbasic ejecuta (tambin decimos llama) un mtodo: REALbasic encuentra memoria que no est en uso para contener los argumentos del mtodo y las variables que hayas declarado con Dim en el interior del mtodo. Las variables que hayan sido declaradas como argumentos del mtodo estn reservadas y nombradas como si se hubiesen declarado con Dim dentro del propio mtodo. REALbasic copia los valores de los argumentos desde el mtodo origen en las variables de argumento dentro del mtodo. REALbasic anota la lnea en la que se encuentra el mtodo de origen que tendr que ejecutar despus de que se haya llamado al mtodo. REALbasic ejecuta el cdigo que se encuentre dentro del mtodo. Una vez que se haya completado el mtodo, si dicho mtodo es una funcin, entonces se copia el resultado de vuelta a la expresin desde la que se hubiese llamado la funcin. Despus de salir del mtodo, y antes de reanudar la ejecucin en el mtodo de origen, REALbasic marca como vaco el espacio que haba sido reservado para las variables y los argumentos del mtodo que acaba de concluir. Sobre el mbito de las Variables Locales Es importante comprender que cualquier variable declarada mediante Dim o declaradas como argumentos en un mtodo existen slo dentro del mtodo en cuestin. Ser bastante frecuente que en un mtodo se declare mediante Dim una variable con el nombre, digamos, de contador y que dicho mtodo llame a otro mtodo que tambin haya declarado una variable con el mismo nombre. Estas dos variables son distintas, y ninguna de ellas podr acceder a la otra. De modo que si cualquier mtodo modica su variable contador no tendr efecto sobre la otra. Estas variables locales se destruyen cuando naliza la ejecucin del mtodo; entendiendo que por destruir nos referimos a cualquier valor que dichas variables puedan contener, y el espacio ocupado por dichas variables es reclamado y disponible de nuevo para ser usado por parte de otra variable distinta. Dado que las variables locales que puede usar un mtodo se crean y destruyen cada vez que se llama al mtodo, sus valores no se conservan entre cada una de las llamadas que se produzcan sobre dicho mtodo. Cuando declaras el tipo de dato para contador dentro de la lnea For, slo existe mientras que se est ejecutando el bucle For. Se borra de la mmeoria despus de la ltima iteraccin del bucle y REALbasic ejecute la siguiente lnea de cdigo dentro del mtodo. La parte del programa en la que se puede acceder o resulta visible una variable, mtodo o propiedad se denomina su mbito. Hasta el ahora hemos utilizado dos niveles de mbito: el mbito de las variables declaradas mediante Dim dentro de un mtodo est limitado a dicho mtodo (o bien el bucle dentro de dicho mtodo) y el mbito Global dentro de los

mdulos. El mbito Global, que est disponible slo en los mdulos, hace que los elementos estn disponibles para toda la aplicacin. Encontraremos otras reglas sobre el mbito a medida que aprendamos ms sobre las diversas caractersticas de REALbasic. Ten en cuenta que puedes modicar los argumentos de un mtodo dentro de ese mtodo, pero slo estars modicando una copia del valor que se ha proporcionado en la llamada al mtodo; una vez que el mtodo nalice el valor pasado permanece inalterado. Puedes utilizar la palabra resevada ByRef precediendo a la declaracin del parmetro (como en: ByRef x As String), en cuyo caso estars operando sobre el valor original, y por tanto modicndolo. Esto resulta especialmente til para devolver mltiples valores desde un mtodo. Recursin Hemos visto el bucle For-Next en una leccin anterior. Ahora vamos a echar un vistazo a un modo completamente diferente de repetir una accin, denominado recursin. 1 Abre el Editor de Ventana para Window1 y selecciona el control slider. Cambia el valor Maximum para el slider Repetitions a 5. De igual modo, asegrate de que est desactivada la caja de vericacin correspndiente a LiveScroll. Esto permitir que resulte ms sencillo el trazado de la ejecucin. 2 Crea un nuevo motdo en el mdulo StringLibrary con los mismos argumentos y tipos de devolucin que RepeatString. Llmalo RepeatString2. 3 Dene el cdigo de RepeatString2 como sigue: Function RepeatString2 (s As String, n As Integer) As String If n <= 0 then Return //sin espacios entre las comillas Else Return s+RepeatString2(s,n-1)+EndOfLine End If Puede que encuentres este cdigo un tanto desconcertante dado que el mtodo se llama a s mismo mediante la segunda lnea Return. Un mtodo recurrente es similar a una prueba por induccin matemtica: Tiene una condicin recursiva, que es una instruccin If-then (o similar), para determinar cul de las siguientes dos cosas ha de hacer; Tiene un caso base, que provoca el hecho de que deje de llamarse a s mismo, y realizar algn paso nal; y Tiene un caso recursivo que causa: La realizacin de un paso no nal, Cambiar cualquier cosa que produzca la nalizacin de la condicin recursiva a lo que ejecute el caso base y por ltimo

Llamarse a s mismo.

En nuestro ejemplo, la condicin recursiva es: n <= 0 (Ten en cuenta que <= signica menor o igial que). El caso base es: Return Y el caso recursivo es: Return s+RepeatString2(s, n-1)+EndOfLine El ltimo paso consiste en devolver una cadena vaca, y el caso no nal consiste en devolver una copia de la cadena, concatenada con una duplicacin ms corta de la cadena. Advierte que cada vez que el caso recursivo vuelve a llamar al mtodo, reduce en una unidad el valor pasado a la siguiente invocacin del mtodo como su n. Recuerda lo que hemos dicho que ocurre cuando se llama a un mtodo: crea una nueva copia desde cero para todas las variables que est utilizando. La copia antigua an est ah, esperando a nalizar la ejecucin. Y cada vez que llamamos de nuevo al mtodo nos aproximamos a la condicin que provocar la ejecucin del caso base y su nalizacin. Una vez que alcance la condicin base, rebobinar a travs de cada uno de los mtodos no nalizados, completando la evaluacin de las expresin que llamaron al mtodo, aadiendo una copia de la cadena y devolvindola en la evaluacin del mtodo anterior en cada etapa. Cuando utilizar la recursin La recursin resulta un tanto extraa y probablemente poco intuitiva para alguien que no haya topado anteriormente con ella. Debes conciderar el uso de la recursin cada vez que quieras escribir cdigo que realice un proceso en el que, cada vez que se haya completado un paso del proceso, la parte restante deba pasarse de nuevo por el mismo proceso. Algunos ejemplos: Crear n copias de una cadena plantea reunir una copia con n-1 copias adicionales. Comer un sandwich implica comer todo el sandwich en el caso de que su tamao sea mnimo; en caso contrario, tendrs que darle un nuevo mordisco y repetir todo el proceso; y Dibujar un rbol, dibujas una rama si dicha rama es realmente corta; de lo contrario, dibujas una rama y dibujas a continuacin una serie de ramas ms cortas unidas a ella. Una vez que te acostumbras al uso de cdigo recursivo, supone por lo general el modo ms sencillo de solucionar un problema. Por cierto, advierte que en nuestro mtodo, podramos haber tenido n = 1 como nuestro caso base (y devolver simplemente la cadena), pero entonces nuestro cdigo no podra

haber sido capaz de manejar cero copias de la cadena. Esto podra haber sido correcto, pero si no ests seguro, es mejor escribir tu cdigo de modo que sea lo ms general posible. Trzalo Deberas cambiar el cdigo en Update de modo que se llame Repeat2 en vez de Repeat, y trazarlo la suciente cantidad de veces como para que entiendas lo que est haciendo el cdigo recursivo. Advierte cmo n se decrementa en uno cada vez que el mtodo se llama a s mismo, y comprueba cmo se aaden a la ventana de la Pila las llamadas aun no nalizadas del mtodo. Experimento Hay muchas cosas que puedes hacer a partir de este punto, combinando las cosas que hemos aprendido hasta ahora: Llama a Update desde el evento TextChanged en el TextEdit1, de modo que todo quede actualizado cuando modiquemos el texto; Prueba a camiar el rango del slider para que abarque varias miles. Ten en cuenta que las cosas comenzarn a ralentizarse a este nivel. Deberas de poder ver que RepeatString2 comienza a ralentizarse considerablemente antes en comparacin con RepeatString. Esto se as porque la creacin destruccin de todas esas variables hace que el programa realice una carga de trabajo adicional para obtener el mismo resultado. Prueba a crear una versin diferente de Update que slo aada o elimine sucientes copias de la cadena para que coincida con el slider, como un modo de lograr que pueda manejar una cantidad mayor de repeticiones de una forma ms eciente. Por ejemplo: si la cadena resultante tiene una longitud de 2000 caracteres, nuestra cadena fuente tiene una longitud de 2 caracteres, y el usuario mueve el slider a 1001, en vez de generar por entero la cadena de 2002 caracteres, podramos observar que slo necesitamos aadir una copia de la cadena fuente al nal. Si en vez de esto el usuario ha movido el slider a 999, entonces podemos observar que slo necesitamos borrar los dos ltimos caracteres. Pista: Para acortar una cadena, utiliza la funcin Left. Ya sabes como puedes alargarla. Tambin has de observar que si el usuario cambia la cadena fuente, no puedes utilizar este atajo: debes de crear toda la cadena de nuevo, de modo que probablemente tendrs que utilizar dos mtodos update diferentes. Prueba a aadir un segundo slider (llmalo Repetitions2). Usa la caja Results para mostrar Repetitions1.value copias de la cadena como un prrafo, seguida por un par de retornos, luego realiza Repetitions2 copias del prrafo. Slo tendras que modicar una linea en update para esto, y estara involucrada la creacin de una expresin que llamase dos veces a RepeatString (de modo que en alguna parte dentro de uno de los argumentos de RepeatString debera de haber otra llamada a RepeatString). Si piensas que es demasiado sencillo, prueba a escribir un mtodo RepeatString3 que pueda tomar dos strings (las denominaremos string y delimitador; delimitador es el trmino informtico para indicar un separador), y dos nmeros. El mtodo devolver el primer nmero de copias de la cadena, seguido del delimitador, y repetir esto la cantidad de veces indicada por el segundo nmero.

Leccin 6 Arreglos y Cadenas Objetivo En esta leccin aprenderemos los fundamentos de manipular cadenas y de cmo utilizar los arreglos (arrays). Tambin vers un ejemplo simple de un algoritmo. Dlo Una Vez Vamos a crear un programa sencillo donde el usuario escribe algo y entonces aparece mostrado en una ventana modal (MsgBox); pero el programa tambin se encarga de registrar todo lo que introduce el usuario, y protestar en el caso de que se introduzca algo dos veces. 1 Crea un nuevo proyecto. Aade un StaticText, un TextField y un PushButton a Window1 de modo que tenga el aspecto que se puede ver en la Figura 27. Figura 27. Cmo congurar la ventana. (Captura FIgura 27) 2 Ajusta la propiedad Title de la ventana a Di algo. Dene el Name de TextField a Entry, y dene la propiedad Text del StaticText a Di algo. 3 Haz clic en el botn Editor de Cdigo (situado bajo la pestaa Proyecto) para cambiar al Editor de Cdigo de Window1. Haz clic en el botn Aadir Propiedad en la barra de herramientas. REALbasic mostrar el rea de declaracin para las propiedades en el rea de edicin de cdigo: Figura 28. El rea de declaracin de propiedad. (Captura Figura 28) Una Propiedad es una variable que pertenece a un objeto. Se declara del mismo modo que se declara una variable mediante el comando Dim. Existe automticamente siempre y cuando tambin exista el objeto. Tambin puedes denir el valor por omisin que quieres que tenga la propiedad una vez que el objeto cobre vida (despus del =). para denir el mbito de la propiedad, haz clic en los tres botones del margen derecho en la declaracin de la propiedad. De izquierda a derecha, son Pblico (que puede ser accedido desde cualquier parte del programa), Protegido (slo puede ser accedido desde el cdigo en la ventana en la que se encuentra y en cualquier subclase de dicha ventana veremos las subclases en una leccin posterior) y Privado (slo puede ser accedido por el cdigo de esta ventana). En una posterior leccin veremos por qu podras desear limitar el mbito de la variable de este modo. Por ahora, dejemos el mbito como Pblico. 4 Introduce Said() como el nombre de la propiedad y dene su tipo de dato a String. Deja vaco el ltimo campo. El nombre de la propiedad y su tipo de dato son obligatorios pero el valor por omisin es opcional. Ten en cuenta que no hay espacios entre Said y el parntesis de apertura.

Sobre los Arreglos Lo que hemos acabamos de hacer es declarar un arreglo (array). Un arreglo es una lista numerada de datos. Cada elemento de la lista debe ser del mismo tipo (en este caso, una cadena). El primer elemento en el arreglo siempre se corresponde con el nmero cero y cuando ests declarando el arreglo, debes indicar cul ser el nmero correspondiente al mximo elemento. Tu cdigo entonces puede pedir el valor correspondiente al elemento cuyo ndice es n, o bien puede denir dicho valor, siempre y cuando el nmero utilizado como ndice se encuentre en los lmites del arreglo. Puedes declarar la propiedad como: Said(10) As String Y entonces tendrs un arreglo de 11 elementos (empezando por 0 y subiendo hasta 10). Si ponemos: Said(0) As String Tendramos un array con 1 elemento. De modo que la forma en la que indicamos a REALbasic un arreglo vaco consiste en no indicar cul es el ndice superior. Por cierto, acostmbrate a contar desde 0. Ocurre una gran cantidad de veces en la programacin de ordenadores. Aadir una Funcin a la Ventana 1 Haz clic en el botn Aadir Mtodo de la barra de herramientas. Dene el nombre del nuevo mtodo como AlreadySaid, declara un parmetro como s as String y dene el Tipo Devuelto a Boolean. El IDE deber tener el siguiente aspecto. Figura 29. La declaracin de AlreadySaid. (Captura Figura 29) No olvides que AlreadySaid es una nica palabra. 2 Introduce el siguiente cdigo en el Editor de Cdigo. //Pre: Nada //Post: s es un elemento de Said, no se cambia ningn otro elemento de Said // y si said ya fuese un elemento, se devuelve true, de lo contrario false Dim counter as Integer //devuelve true si s es un elemento de Said For counter = 0 to UBound(Said) If Said(counter) = s then Return true

end if Next Said.append s Return False El Editor de Cdigo debera tener ahora este aspecto: Figura 30. El mtodo de AlreadySaid. (captura Figura 30) Comentarios Es til incluir comentarios para la gente que vaya a leer el cdigo (incluyndote a t tambin). Debes procurar incluir la suciente cantidad de comentarios para aclarar el cometido del mtodo a quien est leyendo dicho cdigo por primera vez. Un comentario se escribe incluyendo dos barras // en una lnea. Puedes poner cualquier cosa que quieras detrs de las barras, y REALbasic lo ignorar. Puedes incluir comentarios en dos lneas o bien puedes aadirlos al nal de las lneas de cdigo ejecutable. Si haces esto ltimo, entonces se ejecutar el cdigo situado a la izquierda de las barras, mientras que se tratar como comentarios todo aquello que se ponga detrs de las barras. Tambin puedes poner varias lneas en la (cada una de ellas precedida de //) como desees. Aunque puedes escribir lneas REALbasic muy largas, es probable que quieras seguir el ejemplo mostrado un poco ms arriba, y partir dichas frases o prrafos de comentarios en mtiples lneas de comentarios. Existen otros do modos de escribir comentarios, pero deberas evitarlos: Puedes escribir la palabra REM en vez de las dos barras; esto es una reminiscencia del antiguo BASIC, y no destaca tanto sobre el cdigo como el uso de las dos barras. Puedes usar un apstrofe en vez de las dos barras, pero deberas de evitarlo, dado que se utiliza en depuracin (aprenderemos ms de los comentarios con apstrofe en una leccin posterior). Pre- y Post-Condiciones Si ests afrontando un diseo completo, deberas de escribir Pre- y Post-condiciones para tus mtodos, en el caso de que dichas condiciones no sean muy obvias. Una pre-condicin es algo que deba ser cierto para que el cdigo del mtodo funcione correctamente. Con frecuencia disears los mtodos para que sean llamados en un punto concreto de la ejecucin del programa, y deberas describir en qu estado del programa debera ser mediante un comentario de precondicin. Una post-condicin es algo que est garantizado como cierto una vez que se haya completado la ejecucin del mtodo.

En principio, deberas de poder probar que se cumplan todas las precondiciones de cada mtodo en tu programa, inmediatamente antes de que se llame a cada mtodo. Y las postcondiciones te ayudarn a hacer eso. Esto puede parece un tanto exigente, pero pronto encontrars que la escritura de programas complejos y de gran tamo sin bugs resulta un tanto difcil. Si planteas comprobar que se cumplen las precondiciones y postcondiciones de cada mtodo, en cada uno de los pasos realizados, entonces etars contribuyendo a que tus programas funcionen correctamente. Tambin puedes comprobar las condiciones por ti mismo cuando ests depurando el programa. En los ejemplos anteriores, no tenemos precondiciones, de modo que sera legal ejecutar el cdigo en cualquier ocasin. La post-condicin indica a quien consulte el cdigo precisamente lo que hace. Las instrucciones Return Actan como Puntos de Salida Ten en cuenta que podemos Devolver (Return) un valor en el medio de un bucle For que est en ejecucin. Esto terminara de inmediato el bucle, y por tanto tambin el mtodo. Esto signica que si llegamo al nal del bucle For, sabemos que no hemos encontrado lo que estuvisemos buscando, de modo que Devolvemos (Return) falso. Accediendo al Arreglo Ten en cuenta cmo accedemos a un elemento concreto del arreglo: ponemos una expresin numrica en parntesis despus del nombre del array: Said(counter). Esto forma una expresin ms larga cuyo valor es ahora, esencialmente, una variable de cadena. Es una variable de cadena, no slo una cadena, dado que puedes asignar un valor a ello as como obtener su valor, tal y como puedes hacer con cualquier otra variable. En el ejemplo anterior no asignamos directamente a un elemento del arreglo, pero podemos decir cosas como: Said(Counter) = Si es que queremos hacerlo. Existen otra cantidad de modos para aadir elementos o bien eliminar elementos de un array. En este caso, utilizamos el mtodo Append del arreglo para aadir un elemento al nal del arreglo. Echa un vistazo a la ayuda en lnea para consultar otros modos de aadir y eliminar elementos de un arreglo. Por ltimo, puedes hallar el elemento superior de un arreglo mediante la funcin Ubound, tal y como hacemos en nuestro bucle For. Devuelve el valor ms alto del ndice al que puedes acceder legalmente. Esto signica que: MsgBox Said(Ubound(Said)) Sera perfectamente vlido (asumiendo que existe un mnimo de un elemento en el arreglo), pero: MsgBox Said(Ubound(Said) + 1)

Causar siempre un error. Ten en cuenta que dado que el primer elemento de un arreglo tiene un ndice de 0, la cantidad de elementos en los arreglos es su UBound + 1. Completa el programa Aade el siguiente cdigo al manejador del evento Action para el PushButton en la ventana: //Pre: Ninguno //Post: alerta al usuario si la entrada ya se ha realizado con anterioridad, almacena la entrada de modo que podamos indicarlo if AlreadySaid (Entry.text) then MsgBox "Ya has dicho eso." end if //Limpia la entdada despus de que se haya aceptado. Entry.text = "" Ejecuta el Programa Ejecuta ahora el programa, y observa lo que haces cuando escribes algo dos veces. Prueba a usar el depurador para observar cmo funciona el programa (no te olvides de entrar en la lnea que llama a AlreadySaid). Del mismo modo, una vez que hayas ejecutado AlreadySaid un par de veces, echa un vistazo al panel Variables en el depurador, haz clic en Self (para ver las cosas en la ventana en vez del mtodo que ests ejecutando), y haz clic a continuacin en el enlace subrayado prximo a la variable Said para que puedas ver los contenidos del arreglo. Debes pasar por esto porque el depurador te muestra dnde residen las propiedades y las variables. Esto signica que debes acceder a las propiedades de la ventana desde el panel de variables de la ventana. Pero el panel de variables que ves inicialmente cuando se activa el depurador se corresponde con las variables denidas para el mtodo en curso. Ms sobre los arreglos En este programa estamos tratando un arreglo como un conjunto (set) matemtico: es una caja de cosas, y slo queremos saber si una cosa est o no, as como ser capaces de aadir cosas. El nidice (el nmero que proporcionamos para indicar qu elemento queremos del arreglo) es slo un modo de buscar en orden a travs de los elementos. Intenta pensar como se puede un arreglo de otras formas. Por ejemplo, puede utilizarse un arreglo como una funcin para un pequeo rango de enteros de algn valor. Esto se ejecutara con mucha rapidez. Muchos programas precalculan el valor de alguna funcin complicada y almacena los valores en el arreglo, evitando de este modo la necesidad de tener que realizar clculos que requieran una elevada cantidad de tiempo. Experimento Hay varias cosas que puedes hacer a partir de este punto:

Modicar el programa para que slo recuerde, digamos, los ltimos 5 elementos introducidos; Dejar que el programa informe sobre la posicin que ocupaba ya un elemento recin introducido. Dejar que el programa almacene y compruebe slo la primera palabra introducida. Escribir un programa utilizando un arreglo para que acepte una serie de nmeros informando a continuacin de su suma y media. Si tus matemticas te lo permiten, haz lo mismo sin usar un arreglo, calculando la suma y media a medida que introduzcas los nmeros.

Leccin 7 Algoritmos Objetivo En esta leccin comenzaremos a desarrollar y escribir algoritmos. Qu es un algoritmo? El algoritmo es uno de los inventos ms importantes en ciencias de la computacin. He aqu una denicin formal para un algoritmo: Un algoritmo es un procedimiento no ambiguo para la realizacin de una tarea determinada en una cantidad de pasos nitos. Esta denicin est adaptada de The Art of Computer Programming de Donald Knuth. Esto signica que un algoritmo debe ser: Finito: Un algoritmo siemrpe debe nalizar despus de una cantidad nita de pasos (aunque dicho nmero puede ser arbitrariamente elevado, o incluso desconocido); Denido: Cada paso de un algoritmo debe ser concreto (no ambiguo); y Efectivo: Cada paso del algoritmo debe ser posible dentro de un periodo de tiempo nito. Algoritmos y Ciencia de la Computacin Los ordenadores se crearon inicialmente para realizar clculos que produjesen cosas como tablas de navegacin. Posteriormente, se emplearon para almacenar y producir clculos a partir de datos empresariales. En ambos casos, desarrollar y codicar algoritmos era todo en lo que consista la programacin de ordenadores. Este no es ya el caso. Varias de las tareas entregadas a los ordenadores actuales consisten en la toma decisiones, el control de un proceso contnuo, o la ejecucin de una simulacin, frente al completado de clculos nitos. Probablemente tu vehculo cuente con varios ordenadores, por ejemplo; y piensa en la cantidad de ordenadores utilizados para jugar a juegos. Mientras que el desarrollo y empleo de buenos algoritmos es importante para el desarrollo de este tipo de programas, en la actualidad la programacin de ordenadores contempla algo ms que simplemente el desarrollo de algoritmos. No obstante, es tradicional en la ciencia de la computacin el estudio de los algoritmos en su fase inicial y con cierto detalle, de modo que haremos lo mismo. La naturaleza nita de los algoritmos (tanto si funcionan como si no; los ejecutas y nalizan en una cantidad de tiempo determinada) signica que constituyen buenos ejercicios de programacin autocontenidos. Su naturaleza nita tambin hacen que sean muy buenos para examinar problemas de eciencia (lo que veremos en ms detalle en las lecciones nales.) Igualmente, tambi suele dar resultado pensar en los programas de simulacin o de control como aplicaciones repetidas de uno o ms algoritmos. Ejemplo de algoritmo: Contar palabras

1 Inicia un nuevo proyecto vaco, abre Window1, y disala de este modo: Figura 31. La Ventana de Word Counter. (Captura Figura 31) De arriba a abajo, los objetos estn titulados Source, CountButton y WordList. Si quieres mejorarlo y hacer que la ventana sea remidensionable, un buen ajuste para la ventana sera de 260 x 300 pxeles. El objeto inferior es una ListBox. Deberas leer sobre cmo utilizar una ListBox en la documentacin de REALbasic, aunque veremos las caractersticas particulares de este programa a medida que las vayamos necesitando. Dene la propiedad Title de la Window1 a Word Counter. Los ajustes correspondientes del ListBox son: Propiedad Nombre ColumnCount HasHeading InitialValue WordList 2 True Count Word Ajuste

La propiedad InitialValue tiene un tabulador y no un espacio entre los ttulos para cada una de las dos columnas. El mejor modo de introducir los ttulos para las columnas consiste en abrir el dilogo Editar Valor haciendo clic sobre elbotn que contiene los puntos suspensivos (los tres puntos) en el rea del valor. Figura 32. El cuadro de dilogo de Editar Valor. (Captura Figura 32) Deja sin cambios el resto de los valores para el ListBox. Esto es lo que har el programa: el usuario escribe o pega el texto en el campo superior, hace clic en Count y el listado inferior muestra las palabras del texto, junto con el nmero de veces que se repite cada una de ellas. Ahora tenemos que desarrollar un algoritmo que se encargue de contar las palabras. Ya hemos aprendido sobre todas las tcnicas de programacin que necesitaremos para implementar este algoritmo; lo que tenermos que hacer ahora es considerar como debemos combinarlas. Empezar con un Diagrama de Flujo Dibujar un diagrama de ujo puede suponer un modo ecaz de empezar a desarrollar un algoritmo. Un diagrama de ujo es una representacin pictrica de los pasos involucrados en la realizacin de un proceso. Los componentes que utilizas para dibujar una grca de ujo son los mostrados en la Figura 33:

Figura 33. Los elementos de una grca de ujo. (Captura Figura 33) Un diagrama de ujo se crea mediante la unin o enlace de diferentes tipos de cajas. Debera tener una nica terminal de inicio, y una o ms Terminales de salida. Debes escribir texto conciso en las cajas encargado de describir qu es lo que se lleva a cabo en cada etapa, tal y como se muestra en la Figura 34. Figura 34. Grca de ujo para la solucin de un problema. (Captura Figura 34) El diagrama de ujo describe un conjunto de pasos de toma de decisiones y de cmputo, empezando en la Terminal inicial, y siguiendo las echas y cajas, realizando las acciones y tomando las decisiones de las cajas hasta que se llega al Terminal nal. Pseudocdigo Si bien el lenguaje de programacin REALbasic es de muy alto nivel y eciente para escribir cdigo, todos los lenguajes de computador aun son un tanto quisquillosos sobre cada pequeo detalle de lo que precisamos cuando estamos pensando en un algoritmo. Lo que resulta importante cuando comienzas a desarrollar un algoritmo es darte cuenta de la toma de decisiones correcta. Puedes dejar para ms tarde el completado de los aspectos especcos, como las declaraciones de variables y los comandos particulares. Por lo general resulta efectivo describir un algoritmo en algn tipo de lenguaje natural menos formal y estructurado. Esto debe resultar lo sucientemente detallado como para que una persona pueda entender los detalles sobre el funcionamiento del algoritmo, y para que se sienta seguro de que puede programar el algoritmo utilizando un lenguaje de programacin real, pero sin entrar en ms detalles que esos. No existen reglas jas sobre cmo llevar a cabo esta tarea, pero a continuacin te mostramos un ejemplo sencillo de pseudo-cdigo: Figura 35. Pseudo-cdigo para la resolucin de un problema. (captura Figura 35) Esto se lee empezando por la parte superior y realizando cada uno de los pasos cada vez, salvo que en alguna parte se indique dirigirse a algn otro punto. Algoritmo para Contar Palabras Echemos ahora un vistazo a lo que tenemos que hacer para contar el nmero de instancias de cada palabra en la cadena: Necesitamos encontrar cada palabra de la cadena. Esto requiere que decidamos qu dene una palabra (por ejemplo, la puntuacin forma parte de la palabra?); Tenemos que almacenar cada palabra que encontremos en una estructura de datos, junto con un contador del nmero de veces que hemos encontrado dicha palabra; y

Cada vez que encontremos una palabra, necesitamos ver si ya est en la estructura de datos. Si ya est en la estructura de datos, entonces necesitamos incrementar (aadir uno a) su contador; si aun no est en la estructura de datos, entonces necesitamos aadirla a la estructura con un contador de 1. Durante el desarrollo de un algoritmo para implementar esto, tendremos cuatro partes principales: IsWordCharacter: una funcin que indica si un caracter en concreto es un caracter de palabra o no (en el caso de que no lo sea, lo consideraremos como un caracter de separacin, y lo pasaremos por alto); WordPosition: Una funcin que nos indica si una palabra ya ha sido almacenada en nuestra lista de palabras y, en tal caso, dnde se encuentra almacenada dentro de dicha lista; AddWord: Un mtodo para aadir una palabra al listado en el caso de que aun no lo est, y de incrementar su contador en el caso de que ya estuviese guardada; y CountWords: Un mtodo para buscar en la cadena, enviando cada una de las palabras al mtodo encargado de su almacenaje, y determinando donde empieza y termina cada una de las palabras llamando para ello a la funcin que se encarga de denir si se trata del caracter de una palabra. Este no es el nico modo de analizar este problema; y de hecho sera posible escribir todo como un nico mtodo, por ejemplo. Sin embargo, este modo ofrece una separacin natural de las partes que componen esta tarea. Registraremos el contador en un par de arreglos relacionados: la palabra en un ndice en concreto del primer arreglo tendr su contador almacenado en la misma posicin ndice del segundo arreglo. Gestionar esta estructura de datos es una extensin del tipo de cdigo que hemos estado escribiendo en las lecciones anteriores. El algoritmo para separar las palabras de la cadena es ms interesante. Si intentas escribir un mtodo para que se encargue de esto, encontrars que es un poco ms difcil de lo que esperabas. Tendrs que escribir un bucle que mire las letras de una en una, pero al hacerlo, debe decidir correctamente dnde empieza y termina cada una de las palabras, y debe pasar al mtodo que las almacena slo los caracteres que formen parte de la palabra. La estrategia que utilizaremos consiste en iniciar el bucle cada vez mediante uno de los dos estados: InWord o no. (De modo que InWord ser una variable de tipo Boolean). Cada vez que iteremos el bucle, comprobaremos si el siguiente caracter es un caracter de lmite para el estado acfual (de modo que si es InWord, comprobaremos un caracter que no se corresponde a la palabra, y si no estamos InWord entonces se trata de un caracter de palabra). Cuando cambiemos el estado no InWord al estado InWord, habremos encontrado el inicio de una palabra, mientras que lo opuesto signicar que hemos alcanzado el nal de la misma. El cambio de estado tambin marca el nal de una palabra en el caso de que

estuvisemos inicialmente en InWord. Empezamos todo el proceso observando el pimer caracter para decidir con qu estado comenzaremos. Cmo escribir un algoritmo Cuando escribas un algoritmo siempre has de pensar en lo siguiente: La precondicin para el algoritmo, que signica lo que debe congurarse antes de que se pueda ejecutar el algoritmo. En nuestro caso, necesitamos una cadena, y necesitamos mtodos que puedan almacenar las palabras que encontremos en dicha cadena. La postcondicin del algoritmo, lo que signica que los cambios en el estado del programa fuera del mtodo propiamente dicho han tenido lugar una vez que ha concluido el algoritmo. Siempre debes ser capaz de especicar esto con total claridad. En este caso, el nico cambio realizado despus de que se ejecute el programa es que las palabras han pasado por el mtodo de almacenaje. Pero el mtodo puede haber realizado otros cambios al estado general del programa, de modo que necesitamos advertir dichos cambios en el caso de que se hayan producido. Ten en cuenta que el algoritmo cambia los valores de la variable Counter, pero dado que se trata de una variable local, esta desaparece una vez que concluye el mtodo, y por tanto no debemos de preocuparnos sobre esto. Las condiciones que debemos mantener como ciertas a medida que se ejecuta el algoritmo; puede que haya varias etapas durante las cuales se lleven a cabo diferentes acciones. En este caso, estamos incremantando el contador, y pasando una palabra a AddWord cada vez que el contador apunte al nal de una palabra. Los algoritmos tambin pueden utilizar sub-algoritmos, lo que resuelve una pequea parte del problema general. En nuestro caso tenemos un sub-algoritmo, contenido en el bucle For en CountWords. Tambin puede ser considerado en los trminos descritos arriba: Precondiciones para el bucle: La cadena no debe estar vaca; Counter = 1; InWord es True si el primer caracter es un caracter de palabra, y False en el caso contrario. No hemos emitido la ltima palabra de la cadena si la cadena naliza con un caracter de palabra. La invariante del bucle que es lo que mantenemo como cierto al nal del bucle, es similar al de todo el algoritmo, excepto que no enva la ltima palabra al mtodo AddWord en el caso de que la cadena nalice con un caracter que no sea de palabra. Figura 36. Nuestro algoritmo expresado como un diagrama de ujo. (Imagen Figura 36)

Ejercicio: Convierte el diagrama de ujo en pseudo-cdigo Prueba a convertir la Figura 36 en pseudo-cdigo, para ver hasta qu punto has asimilado lo tratado. El cdigo real Aqu est el mtodo real CountWords, y que debes aadir a tu ventana: //Pre: Ninguna //Post: El arreglo Word contiene todas las palabras de Source; //El arreglo Count contiene el contador correspondiente a las palabras en Source Dim InWord As Boolean Dim counter, WordStart As Integer if Len(Source.text)>0 then //si source no est vaco InWord = IsWordCharacter (1)//invariante Inword (abajo) If InWord then//Invariante Wordstart invariant (abajo) WordStart = 1 end if for counter = 1 to Len (Source.text) //Invariantes: //Inword: InWord es cierto si el caracter contador de Source.text ha sido IsWordCharacter //WordStart: WordStart es el ltimo caracter contador dado que el caracter anterior a l no ha sido IsWordCharacter if InWord then if not IsWordCharacter (counter) then AddWord (Mid (Source.text, WordStart, counter-WordStart)) InWord = false //InWord invariant end if //Invariante WordStart: InWord implica que no necesitamos cambiar WordStart else //no est en InWord If IsWordCharacter (counter) then InWord = true //invariante InWord WordStart = counter //invariante Wordstart end if end if next end if //El bucle no detecta el nal de la cadena como un lmite If InWord Then AddWord(Mid(Source.text, WordStart, counter-WordStart)) End If Este cdigo est escrito con una descripcin muy formal de las precondiciones, las postcondiciones y las invariantes del bucle en los comentarios. De hecho hemos

nombrado las invariantes del bucle y hemos intentado probar donde resultan ciertas dentro del bucle. Hacer esto resulta un poco excesivo para un ejercicio tan sencillo, pero deberas realizar algo as (o en ltimo trmino, intentar pensar as) para cualquier algoritmo complejo que vayas a realizar. Lo ms prximo que te encuentres a probar que tu cdigo es correcto antes de que lo ejecutes, menos bugs introducirs en tu cdigo. 2 Aade las siguientes propiedades a la ventana: Count() As Integer y Word() as String. 3 Aade la siguiente funcin a la ventana: Function IsWordCharacter (n As Integer) As Boolean //Pre: Ninguna //Post: Si el caracter se encuentra en la posicin n en Source es una letra o nmero, Devuelve True //de lo contrario, devuelve false Dim c As String c = Mid (Source.text, n, 1) Return (c>="0" and c<="9") or (c>="A" and c<="Z") or (c>="a" and c<="z") El Editor de Cdigo para la funcin IsWordCharacter debera tener este aspecto: Figura 37. El mtodo IsWordCharacter. (Captura Figura 37) Dividir algo as en sus propios mtodos es una buena idea. Podemos cambiar con facilidad lo que dene una palabra cambiando slo un mtodo (quiz haciendo que dependa de un ajustes de las preferencias). Tambin hace que el mtodo encargado de contar las palabras sea ms pequeo y sencillo, dado que no necesita incluir este cdigo. En un proyecto ms complejo, tambin puedes reutilizar este mtodo en otro cdigo de procesamiento de cadenas. 4 Aade la siguiente funcin a la ventana: Function WordPosition (w As String) As Integer Dim counter As Integer //Pre: Ningun //Post: Devuelve el ndice del arreglo dentro del arreglo Word en el caso de que est, o bien -1 si no es as. For counter = 0 to UBound(Word) If Word(counter) = w then return counter End if Next Return 1

Asegrate de que entiendes lo que hace este mtodo1. 5 Aade el siguiente mtodo a la ventana: Sub AddWord (w As String) //Pre: Los arreglos Count y Word tienen la misma cantidad de elementos //Post: Si w est en el arreglo Word, se incrementa el valor de Count en el mismo ndice //de lo contrario, se aade w al arreglo Word, y se incorpora 1 al arreglo de Count //es decir, estamos manteniendo un contador de las palabras enviadas a este mtodo, en los dos arreglos Dim position As Integer position = WordPosition(w) If position = -1 then Word.append w Count.append 1 Else Count(position) = Count(position) + 1 End if Deberas advertir que al dividir WordPosition en una funcin separada permite que el resto del cdigo sea independiente de la representacin de los datos. Es una buena idea mantener certezas como todos estos caracteres son caracteres de palabras lejos del cdigo que las utiliza. 6 Aade lo siguiente al manejador de evento Action de CountButton: //Ejecuta CountWords y copia a continuacin los resultados en WordList Dim counter As integer CountWords For counter = 0 to UBound(Word) WordList.AddRow Str(Count(counter)) WordList.Cell(counter,1) = Word(counter) Next Tal y como habrs podido leer en el caso de que hayas consultado el control ListBox en la documentacin suministrada de serie, el ListBox permite mostrar informacin en un listado o rejilla. Entre sus caractersticas se encuentra el mtodo AddRow, y que se encarga de aadir una la y de denir los contenidos de la primera columna; as como la propiedad Cell, y que te permite denir los contenidos de cada una de las celdas de la rejilla. Las dos lneas en el anterior bucle For, por tanto, se encargan de aadir una nueva la a WordList. Ejectalo Listo. Como de costumbre, deberas ejecutar el programa y probarlo. Tambin deberas probar a insertar puntos de parada y avanzar paso a paso por la ejecucin del cdigo para observalo en accin. Experimenta
1

Ten en cuenta que REALbasic proporciona una funcin IndexOf que hace lo mismo que esta funcin para cualquier arreglo. En ciertos casos escribiremos nuestra propia versin de las funciones incorporadas con el nico propsito del aprendizaje.

Hay muchos modos de ampliar el proyecto desde este punto. Algunas de ellas en orden creciente de dicultad son: Cambia el cdigo para que ignore los nmeros (recuerdas como detectamos si una cadena es un nmero de una leccin anterior?); El cdigo proporcionado no es sensible a la caja (maysculas/minsculas son consideradas del mismo modo cuando se comparan las cadenas), dado que as es como funciona el operador = estndar en REALbasic. Puedes realizar comparaciones que s tengan en cuenta este factor utilizando para ello la funcin StrComp. Prueba a aadir una casilla de vericacin a la ventana que permita al usuario elegir si quiere que el contador de palabras tenga en cuenta la caja o no; Aade un panel independiente para que muestre las palabras ms comunes junto con su contador. Hay dos modos obvios de llevarlo a cabo (una vez se ha creado el arreglo, y a medida que se est creando); y Puedes probar a que el listado se ordene correctamente cuando se haga clic sobre las cabeceras de las columnas. Esto es realmente sencillo de hacer, pero tendrs que leer la documentacin correspondiente al ListaBox para averiguar cmo. La lectura de la documentacin es tan importante que deberas comenzar a hacerlo ahora, en cualquier caso. Conclusin El desarrollo de algoritmos es en gran parte de lo que trata la ciencia de la computacin, y el desarrollo de un algoritmo tiene que ver ms con el arte que con la ciencia. Fundamentalmente es ms una cuestin de prctica, y de leer sobre algoritmos para aprender cmo hacerlos. En esta leccin hemos intentado proporcionarte algunas lneas maestras y un ejemplo sobre cmo plantear el desarrollo de un algoritmo. Esta es buena ciencia de la computacin, y se puede encontrar en lnea una buena cantidad de recursos y discusiones sobre estas y otras virtudes de diseo.

Leccin 8 Tipos de Datos Abstractos Objetivo En esta leccin echaremos un vistazo a la programacin orientada a objetos. Comenzaremos examinando cmo y por qu deberamos crear nuestros propios tipos de datos. Qu es un Tipo de Dato Abstracto? Formalmente, un Tipo de Dato Abstracto (TDA) est compuesto por un conjunto de operaciones que suponen el nico modo de que otro cdigo pueda acceder a un dato en particular. El TDA dene un tipo, y se dice que el dato es de ese tipo. La ventaja que proporciona es que se separa la implementacin de la interfaz. En trminos convencionales de programacin orientada a objetos, esto se denomina encapsulado. Tambin puedes or que el TDA abstrae los detalles de los datos, y que proporciona ocultacin de la informacin. La encapsulacin proporciona las siguientes ventajas: Podemos desarrollar y depurar el Tipo de Dato Abstracto independientemente del resto del programa; Podemos cambiar la implementacin del Tipo de Dato Abstracto sin tener que cambiar cualquier cdigo que lo llame; y Podemos proporcionar acceso a varios tipos similares de fuentes de datos desde un nico cdigo, sin tener que resolver los detalles encargados de diferenciar entre los tipos de datos. Estas ventajas suponen slo un primer atisbo de algo que veremos de forma repetida a lo largo de este curso: queremos ser capaces de descomponer un programa complejo en partes bien denidas que puedan desarrollarse, depurarse, mejorarse y cambiarse independientemente. La segunda ventaja tambin nos permite abordar el desarrollo de un modo incremental: podemos implementar un TDA de un modo rpido y sin pulir para tener el programa funcionando en poco tiempo, y encargarnos posteriormente de anarlo para que sea ms rpido, use menos memoria, o proporcione caractersticas adicionales. Pre- y Post-Condiciones Hemos visto las precondiciones y postcondiciones brevemente en la ltima leccin. Deberas de poder emplear estos conceptos a la hora de denir un Tipo de Datos Abstracto: deberas de indicar de forma lo ms simple y precisa posible qu hace cada una de las operaciones proporcionadas por el Tipo de Dato Abstracto, en trminos de lo que debera de ser cierto antes de que se ejecute la operacin, y qu ser diferente despus. Orientado a objetos implica soporte de serie para los TDA

Si has utilizado otros lenguajes de programacin con anterioridad, deberas saber que puedes emplear las ventajas de los TDA virtualmente en cualquier lenguaje de programacin. Sin embargo, los Lenguajes de programacin orientados a objetos como REALbasic proporcionan caractersticas de serie que soportan de forma explcita la creacin de Tipos de Datos Abstractos, tal y como veremos. Mejorando el Contador de Palabras con TDA 1 Crea una copia del proyecto Contador de Palabras. brelo. Vamos a crear una versin del Contador de Palabras que cuente el texto del Portapapeles. Vamos a hacer que obtenga el texto de un Tipo de Datos Abstracto. 2 En el Editor de Proyecto, haz clic en el botn Aadir Clase. Vers a continuacin un nuevo icono en el Editor de Proyecto, y el panel Propiedades estar listo para que congures sus propiedades: Figura 38. Las Propiedades de la clase CharacterSource. (Captura Figura 38) La nica propiedad que tienes que cambiar ahora es el Nombre, y que deberas denir como CharacterSource, tal y como se muestra en la Figura 38. Acabas de declarar un nuevo tip ode dato en el que puedes almacenar en variables y propiedades en tu programa. El siguiente paso consiste en proporcionarle los mtodos y propiedades adecuados de modo que podamos usarlo como fuente de datos en nuestro contador de palabras. 3 Haz doble clic en el icono correspondiente a la clase CharacterSource para abrir su Editor de Cdigo. 4 Haz clic en el botn Aadir Propiedad y proporciona a la nueva propiedad el nombre ClipBoardSource y el tipo de dato ClipBoard: 5 Haz clic de nuevo en Aadir Propiedad y proporciona a la nueva propiedad el nombre CurrentPosition y el tipo de dato Integer. Referencias a Objeto frente a Escalares Esta es la primera vez que hemos almacenado un objeto en una propiedad o variable. El tipo ClipBoard que hemos declarado para nuestra propiedad ClipBoardSource es un objeto, lo que supone un tipo de cosa distinta de las cadenas, los nmeros y los Booleanos que hemos utilizado en las propiedades y variables hasta ahora. Las propiedades en REALbasic pueden almacenar dos tipos de cosas diferentes: escalares y referencias de objetos. Los escalares son simplemente un valor. Una vez que hayas declarado la variable, puedes comenzar a trabajar con su valor. Una referencia de objeto es diferente: esta indica a REALbasic donde puede ubicar un objeto en la memoria. Cuando declaras la variable o propiedad slo has declarado un contenedor en el cual almacenar la ubicacin de un objeto (adems de haber indicado qu tipo de objeto estar en dicha ubicacin), pero no has creado en realidad dicho

objeto. Una variable o propiedad declarada para que sea un objeto tiene inicialmente el valor especial de Nil, lo que signica que apunta a ninguna parte en concreto. Antes de que puedas comenzar a hacer algo con un objeto, debes coger la variable o propiedad para referirte a l. En este caso, necesitamos pedir a REALbasic que cree un objeto, y que prioporcione una referencia a dicho objeto que podamos almacenar en nuestra variable. Este es el nico modo en el que REALbasic puede acceder a los objetos. Aunque puede parece un tanto extrao, es en realidad un modo natural de trabajar con los objetos y pronto resultar algo habitual para ti. 1 Haz clic en el botn Aadir Mtodo, y nombre el nuevo mtodo Begin sin proporcionar parmetros o un valor de retorno. Dene su cdigo a: //Debe llamarse antes de que se pueda utilizar el objeto CurrentPosition = 0 ClipBoardSource = New Clipboard 2 Aade los siguientes mtodos a la clase: Function CurrentChar as String //Pre: Se ha llamado a Begin dado que se ha modicado el clipBoard; //Este mtodo no es llamado ms veces que la longitud del texto del clipBoard //Post: Cada vez que se llama a este mtodo, se devuelven en orden los caracteres del texto clipBoard CurrentPosition = CurrentPosition + 1 Return Mid (ClipBoardSource.Text, CurrentPosition, 1) Function Finished as Boolean //Pre: Se ha llamado a Begin //Post: devuelve true en el caso de que la ltima llamada a CurrentChar haya devuelto el ltimo caracter del texto del clipBoard, de lo contrario devuelve false Return (CurrentPosition > Length+1) Function Length As Integer //Pre: Se ha llamado a Begin //Post: se devuelve la longitud del texto en el ClipBoard Return Len (ClipBoardSource.text) Cada una de estas funciones no requiere ningn parmetro, pero cada una de ellas devuelve un valor. Para seguir este cdigo, probablemente necesites buscar algunas de las caractersticas de REALbasic (como por ejemplo Len y Mid, as como las caractersticas del objeto ClipBoard).Ten en cuenta que podemos devolver simplemente los resultados de una expresin Booleana (en la funcin Finished).

Puedes ver cmo los mtodos que hemos implementado aqu proporcionan todo lo que necesitamos para iterar la cadena del portapapeles? Ten en cuenta tambin que cualquier cdigo que llame a estos mtodos no tiene por qu conocer nada sobre el origen de la cadena. 3 Aade una propiedad a la ventana y nmbrala ClipBoardSource y proporcinale el tip de dato de CharacterSource. 4 Cambia el parmetro pasado a IsWordCharacter to c as String y cambia su cdigo a: //Pre: Ninguna //Post: Si c es una letra o nmero, devuelve true, de lo contrario devuelve false Return (c>="0" and c<="9") or (c>="A" and c<="Z") or (c>="a" and c<="z") Modica tu mtodo CountWord para que sea: //Pre: Ninguna //Post: el arreglo Word contiene todas las palabras en ClipBoardSource; //El arreglo Count contiene el correspondiente contador para dichas palabras en ClipBoardSource Dim InWord As Boolean Dim c, StringBuffer As String // Inicializa ClipBoardSource ClipBoardSource = new CharacterSource ClipBoardSource.Begin // Invariante c, comenzar *antes* del primer caracter InWord = false //Invariante Inword StringBuffer = "" //Invariante StringBuffer while not ClipBoardSource.Finished //Invariantes: // c: c es el siguiente caracter aun no procesado de ClipboardSource // StringBuffer: StringBuffer se encarga de contener la cadena de caracteres que ser la prxima palabra que se aada a nuestra lista; una vez aadida, o entre palabras, esta cadena est vaca. //Inword: es true si el contador de caracter de Source.text fue IsWordCharacter //Note: A diferencia de StringBuffer, slo necesitamos actuar sobre los lmites de la palabra c = ClipBoardSource.CurrentChar //invariante c if InWord then if not IsWordCharacter (c) or ClipboardSource.Finished then //n de palabra; enva la palabra AddWord StringBuffer //invariante StringBuffer StringBuffer = "" //invariante StringBuffer InWord = false //invariante InWord else StringBuffer = StringBuffer + c end if else //no est en InWord If IsWordCharacter (c) then //WordBegin; comienza el buffering InWord = true //invariante InWord StringBuffer = StringBuffer + c

if ClipBoardSource.Finished then AddWord StringBuffer end if end if end if Wend Aqu puedes ver que llamamos a los mtodos y funciones desde las clases que creamos, exactamente tal y como hacemos con las clases de serie. Es importante reconocer la diferencia entre el tipo o clase (CharacterSource) y una instancia de dicho tipo (ClipBoardSource). En la vida real existe una analoga: Tom Cruise es una instancia de la clase actor; o New York es una instancia del tipo ciudad. Los programadores de ordenadores tambin pueden utilizar un tipo de atajo y decir que New York es una instancia de city. El Bucle While Anteriormente hemos introducido un nuevo tipo de bucle: un bucle While. Tiene una forma similar de un bucle For, pero empieza con la instruccin While consiste de la palabra While seguida de una condicin Booleana y naliza con la palabra Wend. Comprueba la condicin, ejecuta el cdigo que se encuentra dentro del bucle, y repite estos dos pasos una y otra vez hasta que la condicin sea falsa. En qu medida supone el cdigo del TDA una mejora? Hemos cambiado la fuente del texto para contar las palabras, pero eso no constituye una mejora: es un cambio de caracterstica. En qu medida es la escritura de este contador de palabras una mejora? Cuando escribimos cdigo de ordenador, buscamos por lo general estas cosas: Implementar correctamente el comportamiento deseado; Implementar el comportamiento deseado, totalmente depurado y lo ms rpido posible; y Hacer que el cdigo sea lo ms sencillo de modicar como podamos. En algunos casos2 tambin queremos: Hacer que el cdigo se ejecute utilizando la mnima cantidad de recursos (tiempo, memoria, ancho de banda, etc). El cdigo de este proyecto es una mejora sobre el cdigo del ltimo proyecto porque satisface en mejor medida el requerimiento de sencillez en la modicacin. Este benecio no es aparente de forma inmediata, pero en las prximas lecciones veremos cuan sencillo resulta ahora conseguir que nuestro contador de palabras funcione con diferentes fuentes de datos. Este es un principio de diseo general muy bueno: cualquier estructura de datos que crees debera tener una capa de cdigo de interfaz. Este cdigo debera proporcionar las
2

Es un error muy comn entre los programadores obsesionarse sobre la eciencia en una buena cantidad de situaciones donde simplemente no importa.

caractersticas necesarias por el resto del programa para utilizar dichos datos, pero debe ocultar todos los detalles sobre cmo se almacenan realmente dichos datos. La ventaja de los TDA Es importante ver en este punto lo que hemos logrado utilizando un TDA para este proyecto: CountWords no necesita saber nada sobre la fuente de las palabras que est contando. Al contrario, hemos reducido al mnimo las caractersticas necesarias para que haga su trabajo. Ahora, podemos contar las palabras en cualquier fuente de texto implementando una interfaz muy sencilla para dicho texto. No necesitamos modicar CountWords en absoluto. Podemos, en cierto sentido, enchufar una fuente de texto a CountWords. En este caso, se trata del texto de un Portapapeles. En las prximas lecciones veremos el modo tan claro en el que la programacin orientada a objetos soporta esta capacidad de encadenar las cosas. Un ejercicio Hay otra estructura de datos en nuestro programa: la pareja de arreglos que mantiene las palabras y sus contadores. Prueba a implementar esto como un TDA.

Leccin 9 Polimorsmo Objetivo En esta leccin comenzarmos a aprender cmo utilizar el polimorsmo, capacidad que nosp ermite sacar provecho de las similitudes entre ojetos para simplicar nuestro cdigo. Cmo utilizar esta leccin Es probable que te encuentres volviendo a esta leccin en varias ocasiones. Algunas de ellas pueden parecer extraas o contraintuitivas la primera vez que las leas. Qu es el Polimorsmo? El Polimorsmo, de un modo general, es la capacidad para tratar a cosas similares de formas tambin similares. As es como funciona en REALbasic (menos uno o dos detalles que aprenderemos en lecciones posteriores): Como hemos vistao en la ltima leccin, todos los objetos tienen una clase; Las clases estn ubicadas en una jerarqua de clase con forma de rbol (cada clase tiene una superclase y tantas subclases como sean precisas); Las clases heredan todos los mtodos y propiedades de su superclase; Cada clase es su propio tipo, pero las clases tambin son del tipo de su superclase, la superclase de su superclase, la superclase de esta, y todas las superclases hasta que se alcance la clase raz (root) de toda la jerarqua de clases, la clase objeto. Puedes tratar un objeto como una instancia de cualquiera de sus tipos. Esto signica, por ejemplo, que peudes tratar todos los controles de una ventana como objetos RectControl, dado que todos los controles son subclases del objeto RectControl. Por ejemplo, puedes cambiar la posicin de todos ellos sin necesidad de que debas escribir cdigo diferente para manejar cada uno de los diferentes tipos. Esta ltima capacidad es el polimorsmo: podemos introducir comportamientos compartidos en una superclase compartida y escribir el cdigo encargado de trabajar slo con las caractersticas compartidas de los objetos, ignorando de este modo sus diferencias. Utilizado con propiedad, el polimorsmo nos permitir reducir la cantidad de cdigo que debamos escribir y depurar, as como reducir la cantidad de trabajo requerido para mantener y ampliar un programa. Sin embargo, el polimorsmo es una caracterstica sutil y aprender a utilizarlo bien requiere tanto de experiencia como de una buena comprensin de la misma. Gran parte de lo que vamos a hacer en este curso es proporcionarte las pinceladas en el uso efectivo de la programacin orientada a objetos, y gran parte de ello tiene que ver con el uso ecaz del polimorsmo. Nos llevar varias lecciones cubrir todas las caractersticas de programacin orientada a objetos de REALbasic. En esta leccin, aprenderemos las jerarquas de clases, y tambin el uso de eventos para ampliar una superclase. Tambin modicaremos el contador de palabras de las anteriores lecciones de modo que pueda funcionar con diferentes fuentes de texto sin necesidad de realizar modicaciones adicionales. Un ejemplo de jerarqua de clase He aqu el diagrama de parte de una jerarqua de clase interna de REALbasic:

Figura 39. Parte de una jerarqua de clase interna. (captura Figura 39) Un par de ejemplos de este diagrama: Object es una superclase del resto de las clases; Control es una subclase de Object, y una superclase para Line, RectControl, PushButton y TextField. En ciertos casos, puede ser preciso distinguir la superclase inmediata de una clase: RectControles la superclase inmediata de un PushButton, por ejemplo. En otros casos, la superclase inmediata de una clase slo ser llamada por su superclase. En signicado exacto que tenga superclase debera de ser obvio por el contexto. Nuestra jerarqua de clase Como ejemplo adicional, esta es la jerarqua de clase que vamos a crear para esta leccin: Figura 40. La jerarqua de clase para este proyecto. (Captura Figura 40) El contador de palabras polimrco Veamos un ejemplo funcional: 1 Abre el proyecto de la ltima leccin. Recuerda que escribimos el contador de palabras para que obtuviese sus datos a partir de un Tipo de Datos Abstracto? Vamos a modicar nuestro proyecto de modo que dicha fuente de datos sea un objeto de una clase concreta. A continuacin haremos que el mtodo contador de palabras pueda obtener la informacin a partir de una subclase de dicha clase. 2 Abre la clase CharaterSource. Vamos a cambiarla para que no haga nada. En serio. Herencia, Polimorsmo y Clases Abstractas Vamos a convertir CharacterSource en una clase base Abstracta. Su papel consistir en denir una interfaz para un Tipo de Dato Abstracto. Utilizaremos subclases para proporcionar el comportamiento real deseado. No querrs crear un objeto CharacterSource como tal (dado que no hara nada). Crears un objeto de una de las subclases de CharacterSource, pero nuestro mtodo CountWord tratar dichos objetos como CharacterSource y no necesita saber qu objeto es en realidad. 1 Aade cuatro deniciones de evento a nuestra clase. Para ello haz clic en el botn Aadir Denicin de Evento para cada una de las deniciones de evento. Esta accin abre una rea de declaracin con las mismas opciones que tienes para crear un nuevo mtodo. Nombra los cuatro eventos como sigue: Nombre de evento BeginEvent Tipo devuelto (ninguno)

Nombre de evento CurrentCharEvent FinishedEvent LengthEvent String

Tipo devuelto

Boolean Integer

Eventos Las Deniciones de Eventos proporcionan un medio para que el cdigo denido en la superclase llame al cdigo denido en la subclase, sin necesidad de que deba saber nada sobre la subclase. Lo que vamos a hacer ahora es modicar los mtodos en esta clase para que no hagan nada ms que llamar a los eventos que acabamos de denir. A continuacin crearemos dos subclases, una para que devuelva texto del Portapapeles y otra para que devuelva texto de un archivo. 2 Borra la propiedad ClipBoardSource de CharacterSource. Puedes seleccionar cada propiedad en el rea de navegacin del Editor de Cdigo y hacer clic secundario (Comando + clic en el Macintosh) seleccionando a continuacin Borrar en el men contextual. 3 Modica los mtodos en CharacterSource para que sea: Function CurrentChar() As String Return CurrentCharEvent() Function Finished() As Boolean Return FinishedEvent() Function Length() As Integer Return LengthEvent() 4 Cambia al Editor de Proyecto y haz clic en el botn Aadir Clase. Utiliza ClipboardSource como nombre de la nueva clase e introduce CharacterSource como su Super. 5 Haz doble clic sobre la clase para acceder a su Editor de Cdigo. Despliega los Manejadores de Evento en el panel de la izquierda. Podemos ver los cuatro eventos denidos automticamente aqu dado que esta clase es una subclase de CharacterSource. 6 Aade la propiedad que hemos eliminado de CharacterSource: ClipBoardSource As Clipboard 7 Introduce el siguiente cdigo en los cuatro manejadores de Evento BeginEvent: //Pre: Ninguno //Post: CurrentPosition == 0 CurrentPosition = 0

ClipBoardSource = New Clipboard CurrentCharEvent //Pre: Se ha llamado a Begin dado que se ha modicado el clipBoard; // Este mtodo se llama tantas veces como la longitud del texto del clipBoard //Post: cada vez que se llama a este mtodo, se devuelven en orden los caracteres del clipBoard CurrentPosition = CurrentPosition + 1 Return Mid (ClipBoardSource.Text, CurrentPosition, 1) FinishedEvent //Pre: Se ha llamado a Begin //Post: Devuelve true en el caso de que la llamada a CurrentChar haya devuelto el ltimo caracter del texto del clipBoard, de lo contrario false Return (CurrentPosition > Length) LengthEvent //Pre: Se ha llamado a Begin //Post: se devuelve la longitud del texto en el clipBoard Return Len (ClipBoardSource.text) 8 Modica Window1 para que tenga este aspecto: Figura 41. La ventana del Contador de Palabras. (Captura Figura 41) 9 Cambia el nombre del PushButton a CountClipButton y Caption a Count Clipboard. Ahora, necesitamos modicar CountWord para que funcione con el CharacterSource proporcionado como argumento. Cambia su declaracin de modo que sea pasado como parmetro, Source as CharacterSource.: //Pre: Ninguno //Post: El arreglo Word contiene todas las palabras de Source; // El arreglo Count contiene los contadores correspondientes para las palabras de Source Dim InWord As Boolean Dim c, StringBuffer As String Source.Begin // Invariante c, comenzando *antes* del primer caracter InWord = False //Invariante Inword StringBuffer = "" //Invariante StringBuffer While Not Source.Finished //Invariantes: // c: c es el siguiente caracter aun no procesado en Source // StringBuffer: StringBuffer contiene la cadena de caracteres que formar la prxima palabra aadida al listado; una vez aadida, o entre palabras, esta cadena est vaca. // Inword: InWord is true si el contador de caracteres de Source.text fue IsWordCharacter //Note: A diferencia de StringBuffer, slo necesitamos actuar sobre los lmites de la palabra c = Source.CurrentChar //invariante c if InWord then

if not IsWordCharacter (c) or Source.Finished then //Fin de palabra; enviamos la palabra AddWord StringBuffer //Invariante StringBuffer StringBuffer = "" //Invariante StringBuffer InWord = false //Invariante InWord else StringBuffer = StringBuffer + c end if else //no InWord If IsWordCharacter (c) then //WordBegin; comenzamos con el buffering InWord = true //Invariante InWord StringBuffer = StringBuffer + c if Source.Finished then AddWord StringBuffer end if end if end if Wend 10 Dene el manejador de evento Action en el botn Count Clipboard a: //Ejecuta CountWords en el clipboard, y copia a continuacin los resultados en WordList Dim counter As integer Dim Source As ClipBoardSource Source = New ClipboardSource CountWords(Source) For counter = 0 to UBound(Word) WordList.AddRow str(Count(counter)) WordList.cell(counter,1) = Word(counter) Next 11 Dene un punto de ruptura en la parte superior del manejador de evento Action recin creado, introduce algn framento de texto en el Portapapeles (ser suciente con unos cuantos caracteres), ejecuta el programa y avanza por el proceso de ejecucin del cdigo en las clases CharacterSource y ClipboardSource. Vers que los mtodos que llama CountWords desde su argumento Sourcevan en primer lugar a los mtodos de CharacterSource, y que despus baja a los manejadores de eventos en la subclase ClipboardSource. Las funciones devuelven sus resultados en el orden opuesto: primero a la funcin CharacterSource que la llam y despus a CountWord desde el que se llam originalmente el mtodo. Clases frente a Objetos Es importante ser claro sobre la terminologa: la clase es la denicin de lo que hace el objeto; el objeto es la cosa realmente usable que creamos cuando se ejecuta nuestro programa. El objeto contiene datos y hace las cosas denidas por la clase. Decimos que un objeto es una instancia de la clase. Un objeto siempre es una instancia de ms de una clase: en este caso, Source es una instancia tanto de ClipboardSource como de CharacterSource. Dentro del manejador de evento Action del botn, lo tratamos como un ClipboardSource, dado que necesitamos crear una clase totalmente funcional y no abstracta que haga cosas realmente. Sin embargo, CountWord tiene una variabla CharacterSource como su argumento. Cuando llamamos a CountWord, su argumento Source termina apuntando al mimso objeto que

hemos creado (recuerdas nuestra discusin sobre cmo las variables de objeto no contienen un objeto, sino que slo se reeren a ellos?). Polimorsmo en accin Esto es polimorsmo en accin: podemos pasar a CountWord cualquier clase que tenga CharacterSource como su superclase, sin necesidad de que debamos modicar el mtodo CountWords. Cualquiera de los detalles requeridos para que funcione con una fuente de datos en particular sern proporcionados en los manejadores de eventos de la subclase CharacterSource en cuestin. Esto signica que podemos depurar CountWords como un elemento aislado, reduciendo as la cantidad de cdigo que necesitamos escribir para contar las palabras provenientes de una nueva fuente de datos. Veremos eso justo ahora en el cdigo que implementemos como comportamiento del botn Count File... Ms sobre Eventos Los eventos suponen el mecanismo ms imporante de extensin en REALbasic. Los eventos que denas e interceptes en las clases son el mismo mecanismo que los manejadores de eventos que hemos estado escribiendo para los controles. Por ejemplo puedes crear tu propia clase de botn especializada, creando para ello una nueva clase y deniendo su Super como PushButton y proporcionando a continuacin el cdigo en su manejador de evento Action o de otros eventos. Tambin puedes denir nuevos eventos en tu nueva clase y que estarn disponibles para cualquier subclase futura, as como para cualquier instancia de dicho botn que arrastres desde la ventana de proyecto hacia la Ventana creada. Los eventos, como mecanismo de ampliacin, son nicos de REALbasic. Otros lenguajes de programacin otientados a objetos utilizan mecanismos de extensin muy diferentes denominados sobreescritura de mtodos. La sobreescritura de mtodos tambin est disponible en REALbasic, y aprenderemos sobre esto en posteriores lecciones. No busques mucho consejo sobre cmo utilizar los eventos o bien sobre cundo utilizar los eventos en vez de la sobreescritura de mtodos. Aparte de lo que vayamos a desarrollar en este curso, y de lo que puedas encontrar en Internet por parte de otros programadores de REALbasic, o bien en los escasos libros sobre REALbasic, no hay mucha informacin al respecto. El Contador de Archivos Ahora, vamos a crear el cdigo para que funcione el botn Count File... Como de costumbre, y en el caso de que lo necesites, consulta la informacin relativa a la gestin de archivos en REALbasic utilizando la referencia incorporada. 1 En el Editor de Proyecto, crea una nueva clase. Nmbrala FileSource y dene su Super a CharacterSource. 2 Abre el Editor de Cdigo de la clase y aade las siguientes propiedades: Nombre CurrentPosition TheStream Integer BinaryStream Tipo de Dato

3 Aade el siguiente cdigo a los Manejadores de Eventos: BeginEvent CurrentPosition = 0 TheStream.position = 0 CurrentCharEvent CurrentPosition = CurrentPosition + 1 Return Chr(TheStream.ReadByte) FinishedEvent Return CurrentPosition > Length LengthEvent Return TheStream.Length Un problema menor En el cdigo anterior escribimos nuestro propio medio para detectar el nal de un archivo (manteniendo un contador de CurrentPosition, y comparndolo con la longitud del archivo). El BinaryStream proporciona tanto la propiedad Position como la propiedad EOF, pero el modo en el que estn implementadas no nos sirven a nuestro propsito. EOF es True antes de que hayamos ledo el ltimo caracter, y Position ser igual a la longitud del archivo tanto antes como despus de haber ledo el ltimo caracter. De modo que no podemos escribir un bucle While apropiado basndonos en cualquiera de estas propiedades. Por ejemplo, si escribisemos: Function FinishedEvent() As Boolean Return TheStream.EOF No podramos devolver el ltimo caracter del archivo. Si escribisemos: Function FinishedEvent() As Boolean Return TheStream.Position = TheStream.length Tendramos el mismo problema. Pueden buscarse otros modos de utilizar estos mecanismos incorporados para leer el ltimo caracter, pero no sin hacerlo excesivamente complicado como para que no falle cuando intentemos leer un CharacterSource cuya longitud sea de cero caracteres (intntalo!). Sin embargo, este no es un gran problema; slo hemos de escribir nuestro propio mecanismo. 1 Aade el siguiente mtodo a la clase FileSource: Sub SetFile(f As BinaryStream) TheStream = f 2 Aade el siguiente cdigo al manejador de evento Action para el botn Count File...: //Solicita un archivo al usuario y ejecuta a continuacin CountWords para dicho archivo, //y copia los resultados en WordList

Dim Counter As Integer Dim Source As FileSource Dim f As FolderItem Dim s As BinaryStream Source = new FileSource //Solicita el archivo f=GetOpenFolderItem("application/text") If f<>Nil then s = f.OpenAsBinaryFile(False) Source.SetFile s CountWords(Source) For Counter = 0 to UBound(Word) WordList.AddRow str(Count(counter)) WordList.cell(counter,1) = Word(counter) Next End if Advierte como hemos aadido un mtodo adicional a nuestra clase. Los objetos del tipo CharacterSource garantizan el soporte de cuatro mtodos (Begin, CurrentChar, Finished y Length), pero los objetos del tipo FileSource soportan un mtodo adicional (SetFile). Observa que el botn sabe que est trabajando con un FileSource, de modo que puede denir el archivo, pero CountWords no sabe nada sobre este mtodo adicional, y tampoco necesita saberlo. Tipos de Archivo Necesitamos indicar a REALbasic qu tipos de archivos intentamos abrir. Deberas leer el Captulo 8 de la Gua del Usuario para obtener informacin adicional sobre los Tipos de Archivo. 1 Selecciona Proyecto > Aadir > Grupo de Tipo de Archivo. Vers un nuevo icono FileTypes en la pestaa Proyecto. Haz doble clic sobre l para acceder al Editor de Tipos de Archivo: Figura 42. El editor de Grupo de Tipo de Archivo. (Captura Figura 42) 2 Haz clic sobre el botn Aadir Tipo de Archivo para aadir una nueva la al listado. Introduce la siguiente informacin: Campo Muestra Nombre Nombre de Objeto MacType MacCreator Valor application/text applicationText TEXT ????

Campo Extensiones

Valor . 1st;.nfo;.readme;readme;.tx t

Prubalo Listo. Probablemente quieras trazar la lectura de un archivo (muy pequeo). Revisin Hemos visto los aspectos bsicos en la implementacin de una jerarqua de clase, as como del empleo del polimorsmo. Deberas de volver atrs y leer de nuevo el material introductorio que trataba las caractersticas utilizadas en este programa. Centrate en la jerarqua de clase y en el mecanismo de eventos que nos permite tratar dos clases diferentes como si fueran la misma. Advierte como se trata de una extensin de la idea correspondiente al Tipo de Dato Abstracto. Diseo Orientado a Objeto Un tema principal de este curso est relacionado sobre cmo disear aplicaciones cuyas partes claramente separadas nos permitan desarrollar y depurar de forma independiente partes individuales de programas complejos. Hemos visto cmo los mtodos y los Tipos de Datos Abstractos nos ayudan a realizar dicha labor. La herencia y el Polimorsmo llevan dicha idea un paso ms all: no slo puedes implementar diferentes TDA de forma separada, sino que tambin puedes desarrollar y depurar comportamientos compartidos entre los ojetos que implemente el mismo TDA una vez. Los buenos diseos orientados a objeto tendrn con frecuencia una buena cantidad de este tipo de cdigo situado en la parte superior de las jerarquas de clase, lo que signica que una buena cantidad del cdigo del programa es generalizado y compartido. Alcanzar este tipo de eciencia en el diseo tiene lo mismo de arte que de ciencia. Son precisos aos de experiencia en programacin y una buena cantidad de cdigo otientado a objeto bien escrito para desarrollar este nivel de aptitud en el diseo orientado a objeto. Explicaciones/Referencias Los eventos estn tratados en el Captulo 5 y en la seccin Aadir Deniciones de Eventos del Captulo 9 en la Gua del Usuario de REALbasic. Desafortunadamente, la Gua del Usuario de REALbasic slo trata el polimorsmo usando el otro mecanismo (mtodos virtuales que trataremos posteriormente) Pero ten en cuenta que si lees la seccin Aadir Nuevos Eventos en el Captulo 9, lo que est describiendo es polimorsmo. Estamos tratando estas cuestiones a pequeos sorbos, de modo que habr que esperar para obtener una buena comprensin de estos temas hasta que hayamos realizado previamente algunas lecciones adicionales. Uno de los principios de diseo importantes a los que queremos adherirnos es que las superclases no deberan de saber nada sobre sus subclases. Al denir un evento y llamarlo, una superclase est deniendo un modo de comunicarse con su subclase, sin importar cul pueda ser, al tiempo que consigue mantener su ignorancia sobre los detalles de dicha clase.

Si lees el Captulo 9, este puede ayudarte a entender que el mecanismo de Mtodos Virtuales descrito es otro modo de conseguir que se produzca una comunicacin entre la subclase y la superclase (pero en este caso, la subclase es la encargada de mantener el control). Hemos empezado con los eventos, dado que los necesitas para crear subclases de los controles, y de hecho permaneceremos con los eventos durante algn tiempo ms dado que queremos mantener las cosas simples por el momento. Ejercicio Adicional Prueba a aadir una TextBoxSource que cuenta los contenidos de un TextField. Ten en cuenta que el TextField ya es una clase, y dado que slo puedes denir una superclase para una clase, no puedes crear una subclase de TextField que tambin lo sea de CharacterSource. En vez de ello tendrs que escribir algn tipo de clase adaptadora que incorpore el mtodo SetTextBox, similar al SetFile de FileSource.

Leccin 10 Eliza Objetivo En esta leccin crearemos un programa con el que pondremos en prctica nuestros recin adquiridos msculos de programacin. Continuaremos siendo eles al tipo de cosas que ya hemos venido utilizando hasta ahora, sin aventurarnos en nuevo material relacionado con los TDA y con el polimorsmo. Slo estamos intentando ver qu aspecto tiene un programa ligeramente ms complejo. Qu es Eliza? Eliza es un programa clsico de ordenador. El programa pretender dialogar con el usuario, actuando como un psiquiatra o consejero. El usuario escribe texto en ingls (o castellano) y el programa parece responder de forma inteligente tambin en ingls (o en castellano). Planicando el programa Debemos implementar varias cosas diferentes para asegurarnos de que el programa funciona. Necesitamos proporcionar: Un modo de obtener las frases que buscamos y las respuestas correspondientes en dicho programa; Almacenamiento y recuperacin para cada una de las frases y de las respuesas; y La interfaz de usuario y la lgica que implementa las preguntas y respuestas reales. Intenta decidir cmo haras estas cosas antes de continuar. Cargando frases de un archivo Cargaremos las frases desde un archivo de texto que resida en disco. Ya hemos visto antes cmo leer un archivo, pero en esta ocasin tenemos que almacenar alguna informacin estructurada en el archivo. El archivo podr contener mltiples respuestas. Cada respuesta consistir de una o ms palabras o frases para cada una de ellas, y de una o ms posibles respuestas. Esto signica que debemos separar: Cada respuesta de la siguiente; En cada una de las repuestas, las frases a buscar para cada una de las respuestas; y Dentro de las frases y las respuestas, los trminos buscados de forma individual o respuestas para cada una de ellas. Llevaremos esto a cabo teniendo cada respuesta en una lnea separada dentro del archivo. A continuacin separaremos las frases de bsqueda de las respuestas mediante un tabulador. Por ltimo, separaremos cada una de las frases de bsqueda de la otra, y cada una de las posibles respuestas entre s mediante una barra inclinada (/). De modo que cada una de las lneas del archivo podra tener el siguiente aspecto (el gran espacio en la lnea es donde se encuentra el tabulador): mum/mom/mother Tell me more about your mother./What does this tell us about your mother?

Indicaremos las respuestas aleatorias que daremos cuando no exista una coincidencia, mediante una lnea que est vaca antes del tabulador. Caracteres ASCII y Unicode Los ordenadores representan las letras como nmeros. Hay dos formas de hacer esto en REALbasic: Usando el conjunto de caracteres ASCII (American Standard Code for Information Interchange), un conjunto de 127 caracteres entre los que se incluyen las letras maysculas y minsculas, los numeros, la puntuacin y otras, incluyendo algunos caracteres de control (como el tabulador); y Utilizando el conjunto de caracteres Unicode, un conjunto de caracteres mucho ms amplio dirigido a aglutinar cada uno de los smbolos preciso para representar cada lenguaje existente en la Tierra, as como una gran cantidad de otros smbolos. El ASCII es un viejo estndar. Es importante por dos motivos: 1) compatibilidad con otros sistemas; y (2) porque los caracteres ASCII caben en un nico byte 3. Unicode es un estndar ms reciente para los principales sistemas informticos. Es importante porque la mayora de la gente del mundo necesita ms que simplemente el conjunto de caracteres Roman (o Latino) para comunicarse. La nica desventaja signicativa del Unicode es que requiere del uso de dos bytes para representar cada uno de los caracteres, de modo que precisa el doble de espacio para almacenar el texto en Unicode, y tambin es un poco ms lento a la hora de procesarlo. Unicode ha sido diseado de modo que los primeros 127 caracteres sean los mismos que en el conjunto de caracteres ASCII. REALbasic almacena internamente los caracteres en ASCII si el sistema operativo en el que est funcionando utiliza los caracteres Latino (Roman), y Unicode en los otros sistemas. Sus operaciones de cadenas normales operan sobre ASCII o Unicode en consecuencia. Tambin existen versiones B de todas las operaciones (AscB, etc) que funcionan slo sobre los bytes. Consulta la referencia incluida de serie para obtener ms informacin. Para nuestros propsitos, Slo necesitamos ser capaces de identicar dos caracteres no imprimibles, algo que haremos utilizando la funcin Chr (y que deberas consultar). StringResponder Comencemos. Dado que se trata de un programa bastante sencillo, pondremos la mayora de las caractersticas en una nica clase. 1 Crea un nuevo proyecto. Aade una nueva clase, sin asignar una Super y cuyo nombre sea StringResponder. Abre su Editor de Cdigo. 2 Aade las siguientes propiedades:
3

Para los no iniciados, un byte es la unidad estndar de espacio de almacenamiento en un ordenador. Consiste de ocho dgitos binarios (bits; cada uno de los cuales puede ser 1 o 0), y es capaz de representar cualquier de los 256 posibles valores (digamos, los nmeros en un rango de 0 a 255). Se han empleado varios esquemas para lograr que los bytes representen nmeros ms grandes, fracciones y texto.

Nombre RandomResponse() RespondWith() SearchFor() String String String

Tipo de Dato

3 Crea un nuevo mtodo y nmbralo LoadFromFile, utilizando como parmetros f as FolderItem, ElDelimiter as String, RespDelimiter as String). No tiene tipo devuelto. 4 Introduce el siguiente cdigo en LoadFromFile. //Pre: f es un folderitem vlido de texto, delimitado tal y como se describe a continuacin. //Post: Los registros, delimitados por Chr(13), se cargan en las respuestas, //con la respuesta delimitada de la cadena buscada por //estar delimitada mediante RespDilimiter, y mltiples respuestas o bsqueda //delimitadas por ElDelimiter //Ten en cuenta que las Respuestas Aleatorias estn indicadas mediante bsquedas vacas Dim InputFrom As TextInputStream Dim InputLine, searchForIn, RespondWithIn As String Dim Counter1, Counter2 As Integer InputFrom = f.OpenAsTextFile //Divide searchForIn de RespondWithIn While not InputFrom.EOF InputLine = InputFrom.ReadLine searchForIn = Trim(NthField(InputLine, RespDelimiter, 1)) RespondWithIn = Trim(NthField(InputLine, RespDelimiter, 2)) If searchForIn <> "" then //Sperar los mltiples searchForIns, RespondWithIns y los empareja for Counter1 = 1 to CountFields(searchForIn, ElDelimiter) for Counter2 = 1 to CountFields(RespondWithIn, ElDelimiter) AddResponse NthField(searchForIn, ElDelimiter, Counter1),_ NthField(RespondWithIn, ElDelimiter, Counter2) next //Counter2 next //Counter1 else //Vaca searchForIn, para hacer algunas aleatorias //Aade todas las RespondWithIns a RandomResponse for Counter2 = 1 to CountFields(RespondWithIn, ElDelimiter) AddRandom NthField(RespondWithIn, ElDelimiter, Counter2) next //Counter2 end if //searchForIn Wend InputFrom.Close Deberas echar un vistazo a las funciones que no hemos visto antes, como por ejemplo NthField y Trim.

Este mtodo puede parecer largo, pero los comandos de cadenas de REALbasic ren realidad hacen que sea bastante directo: separamos las dos partes principales de la lnea, y a continuacin nos movemos por cada una de las partes. Separamos el almacenamiento de la informacin en mtodos como por ejemplo AddResponse. 5 Aade los siguientes mtodos: AddResponse (S as String, R as String) SearchFor.Append S RespondWith.Append R AddRandom(R as String) RandomResponse.Append R 6 Lo ltimo que necesitamos en nuestra clase es el mtodo qu ese encarga de obtener la respuesta: FindMatch(S as String) as String //Pre: Existe como mnimo un elemento en RandomResponse //Post: Busca todos los elementos de SearchFor que estn en S, y devuelve una coincidencia aleatoria que concuerde con la cadena RespondWith //Si no se encuentran correspondencias, devuelve una cadena aleatoria RandomResponse Dim Matches() As Integer Dim Counter As Integer //Crea la lista de coincidencias For Counter = 0 to UBound(SearchFor) if Instr(S, SearchFor(Counter)) <> 0 then Matches.Append Counter end if Next //Devuelve una coincidencia aleatoria o una respuesta aleatoria If UBound(Matches) <> -1 then //Random Match Return RespondWith(Matches(RandomInteger(UBound(Matches)))) Else //Respuesta Aleatoria Return RandomResponse(RandomInteger(UBound(RandomResponse))) End if Este mtodo busca en la lista de palabras de bsqueda, y en el caso de que se encuentre una, se aade su ndice al arreglo Matches. Al nal del proceso elegimos uno de los ndices del arreglo de forma aleatoria, y devolvemos la respuesta coincidente. Si el arreglo de coincidencias est vaco entonces devolvemos una de las cadenas de RandomResponse. Ahora slo tenemos que unir el resto. En primer lugar, necesitamos completar la Function RandomInteger(Top As Integer) As Integer utilizada por FindMatch. Lo aadiremos a un mdulo (recuerdas los mdulos?).

7 Crea un nuevo mdulo. Nmbralo Random y aade la funcin RandomInteger con el parmetro Top as Integer y con un tipo devuelto de Integer. Introduce este cdigo. //Devuelve un entero aleatorio en el rango de 0.. Top Return round(rnd*Top) Necesitamos una funcin que nos proporcione un nmero aleatorio entre 0 y un nmero dado. La funcin Rnd de REALbasic devuelve una fraccin entre 0 y 1. Puedes utilizar el nmero rnd como equivalente de uno entre todos para una cantidad determinada, de modo que al multiplicarlo por top y redondearlo al nmero entero ms cercano, obtenemos el valor que queremos. 8 Ahora necesitamos crear nuestra interfaz de usuario. Abre Window1 y congura una interfaz de usuario como esta: Figura 43. La ventana Eliz. (Captura Figura 43) El TextArea de mayor tamao tiene como nombre Discussion; el ms pequeo se llama Entry. Desactiva la propiedad Enabled correspondiente a Discussion en el panel de Propiedades. 9 Abre el editor de cdigo correspondiente a la ventana. Aade una propiedad: Eliza As StringResponder. 10 Aade los siguientes mtodos: HandleEntry //El usuario ha introducio algo. Manjalo. Discussion.Text = Eliza.FindMatch(Entry.Text) Entry.Text = "" SetResponder(R as StringResponder) Eliza = R La razn por la que ponemos esto en mtodos en vez de hacerlo simplemente en manejadores de eventos es porque permitiremos que el usuario introduzca lo que haya escrito de varias formas. 11 Introduce lo siguiente como manejador de evento KeyDown para Entry: Dim K As Integer K = Asc(Key) If Key = Chr(13) or Key = Chr(3) then HandleEntry Return True Else

Return False End if Esto permite que el usuario introduzca lo que haya tecleado pulsando las teclas Enter o Retorno. 12 Aade la llamada de mtodo HandleEntry al manejador de evento Action del botn. Ahora slo queda una cosa por hacer: tenemos que crear un StringResponder y cargar sus contenidos cuando se inicie la aplicacin. 13 En el Editor de Proyecto, haz doble clic sobre la clase App y aade el siguiente cdigo en su manejador de evento Open: //Inicializa Eliza desde archivo Dim f As FolderItem Eliza = New StringResponder f = new FolderItem f = f.Child("Responses.txt") If f<>Nil then Eliza.LoadFromFile f, "/", chr(9) Else MsgBox "Error: No se ha encontrado Responses.txt." Quit End if Window1.SetResponder Eliza Deberas detenerte y leer los componentes nuevos, en particular la propiedad child de los FolderItems. Un nuevo FolderItem comienza apuntando a la carpeta en la que reside la aplicacin (o cuando ests ejecutando desde el IDE, la carpeta en la que hayas guardado el proyecto), de modo que este cdigo intentar cargar un archivo llamado Responses.txt desde esa misma carpeta. 14 Aade la siguiente propiedad a la clase App: Eliza As StringResponder mbito de los Identicadores Es posible que hayas advertido que hemos denido dos propiedades de idntico tipo y nombre (Eliza As StringResponder tanto en la clase App como en Window1). Es importante comprender que se tratan de dos propiedades independientes, y que se pueden referir potencialmente a dos objetos distintos (aunque en este caso terminen rerindose al mismo objeto). Esto funciona porque todos los identicadores (el trmino de ordenador utilizado para los nombres en un programa informtico) de un programa tienen un mbito (lo que signica la parte del programa en la que resulta vlido dicho identicador). Cuando te reeres a un nombre en tu cdigo, se busca el signicado del nombre siguiendo este orden:

Variables locales, denidas y vlidas slo dentro del mismo mtodo, declaradas mediante un comando Dim; Propiedades, mtodos o nuevos eventos visibles en el mismo Editor de Cdigo (lo que signica en la misma clase o ventana); Propiedades o mtodos en una superclase (en el caso de que no se hayan denido como Private); y Propiedades Globales o Pblicas o mtodos en un mdulo o propiedades pblicas o mtodos en otras ventanas y clases. Esto signica que el identicador denido en la parte superior de esta lista evitar que el cdigo pueda usar un identicador que de otro modo pudiese ser visible en la zona inferior de la lista. De igual modo, recuerda que salvo que una propiedad o mtodo est declarado como Protegido o Privado cuando se dene el mtodo, siempre has de referirte a l desde cualquier parte del programa utilizando MiObjeto.AlgunaPropiedad o MiVentana.AlgunMetodo (e igual con el resto) empleando la notacin con punto. Prubalo Debera de estar preparado un archivo Responses.txt sencillo en el mismo lugar donde accediste a esta leccin. Si quieres escribir tu propio archivo, utiliza un editor como NotePad o bien BBEdit; asegrate de guardar el nuevo archivo como un archivo de Texto. Eso es todo. Como de costumbre, deberas de probar el programa y trazar aquellas partes en las que ests interesado. Ejercicios adicionales Obviamente puede mejorarse este proyecto de varias formas. He aqu algunas ideas: El proyecto debera mantener un registro mejor de las respuestas. Por el momento, si introduce dos veces lo mismo, el ordenador devolver en algunas ocasiones la misma respuesta dos veces. Cmo podra solucionarse esto? (una sugerencia: las respuestas no deberan ser aleatorias de entre las posibles coincidencias, sino en orden. Entonces vuelve a reordenar las respuestas de modo que la ltima se coloque al nal de la lista. Puedes mezclar la lista antes de empezar, para conseguir que tenga cierta aletoriedad entre ejecuciones diferentes. Tambin hay otras soluciones, como etiquetar las respuestas de algn modo). Para mezclar una lista, recrrela e intercambia cada elemento con otro seleccionado al azar; El proyecto podra empezar solicitando el nombre del usuario, e incorporar a continuacin el nombre como parte de la respuesta (digamos, sustituyendo un caracter especial como por ejemplo el asterisco * por el nombre). Si te sientes conado y ms ambicioso, permite que las respuestas muestren un cuadro de dilogo y almacenen la respuesta; despus permite que se pueda utilizar la respuesta en otras respuestas. El programa tendr que permitir que el archivo Responses.txt contenga dichas respuestas, y no podr saber por anticipado cules sern sus nombres, de modo que necesitar otro listado para almacenar el nombre de las respuestas. Ahora tendrs dos pares de arreglos con el mismo papel (permitindote buscar un valor en el

segundo arreglo en funcin del valor del primer arreglo; el nombre tcnico para esta estructura de datos es una tabla de smbolos). Puede que quieras implementar una clase SymbolTable (recuerda las ventajas de los TDA) para que se encargue de realizar ambas tareas.

Leccin 11 Eventos y Controles Objetivo En esta leccin continuaremos nuestra exploracin de las caractersticas de Programacin Orientada a Objeto (POO / OOP; Object Oriented Programming) de REALbasic. Eventos y Controles En la leccin 9 vismos el modo en el que los eventos nos permiten enlazar el cdigo denido en una superclase con el cdigo de su subclase. Este es el mismo mecanismo utilizado por las clases incorporadas en REALbasic para proporcionarnos manejadores de eventos en los que podemos aadir nuestro cdigo utilizando la ventana correspondiente al Editor de Cdigo. En esta leccin utilizar los eventos del TextField para crear una nueva versin del EditField que slo acepte nmeros. 1 Abre un nuevo proyecto. 2 Crea una nueva clase denominada NumEdit, deniendo TextField como su superclase. 3 Abre el Editor de Cdigo para NumEdit y aade el siguiente cdigo en el manejador de evento KeyDown de la clase: If (Key > "0") and (Key < "9") then Return False Else Return True End if El argumento Key del manejador del evento representa la tecla que ha sido pulsada. Y el valor de retorno Booleano (True o False; verdadero o falso) del manejador del evento indica a la clase interna de REALbasic qu ha de hacer con la tecla que se ha pulsado: si la funcin devuelve True, entonces la tecla se ignora; de lo contrario, la pulsacin de la tecla se procesa normalmente. De hecho, las funciones en REALbasic siempre han de devolver algo. Si no devuelves de forma explcita un valor, entonces la funcin devolver un valor de zero (o, una cadena vaca, False, Nil, etc, dependiendo de cul sea el tipo de de retorno de la funcin). Ten en cuenta que cuando no se proporciona un manejador de evento en una subclase, cuando la cuperclase llama a esta funcin REALbasic devuelve automticamente el valor por defecto False en la llamada. De modo que, como podras esperar, si no proporcionas una subclase de TextField con un manejador de evento KeyDown entonces se limitar a procesar cada pulsacin de tecla con normalidad.

4 Cambia al Editor de Ventana de Window1 y utiliza el men desplegable situado sobre los controles para camboar el listado de los controles internos a los controles del proyecto. NumEdit aparecer listado aqu. 5 Arrastra la clase NumEdit desde el listado de Controles del Proyecto hacia la ventana, y ejecuta el programa. Advierte que hace prcticamente lo que queramos, pero que no soporta las teclas de borrado o de cursor. solucionemos eso. Para ello, necesitamos conocer los cdigos ASCII de las teclas que queremos habilitar. Podemos buscarlas en la documentacin o en cualquier parte en Internet, pero resulta ms sencillo averiguarlo nosotros mismos. Cambia de nuevo al listado de los Controles incorporados y arrastra un TextField estndar sobre la ventana y aade a continuacin el siguiente cdigo en su manejador de evento KeyDown: MsgBox str(Asc(key)) Como de costumbre, puedes buscar Str y Asc en la documentacin incorporada. 6 Ejecuta el programa, haz clic sobre nuestro nuevo TextField, y observa los nmeros que aparecen cuando pulsas las teclas de cursor y la tecla de borrado. 7 MOdica el cdigo del manejador de evento Keydown correspondiente al NumEdit para que sea el siguiente: If (Key >= "0") and (Key <= "9") then Return False elseif Key >= Chr(28) and Key <= Chr(31) then//tecla de cursor Return False Elseif Key = Chr(8) then //tecla borrar Return False Else Return True End if 8 Ejecuta el programa y comprueba que nuestro nuevo TextField nos permite utilziar ahora las teclas de cursor y la tecla Borrar. Podemos mejorar aun ms la clase permitiendo que el usuario pueda introducir una coma para los valores decimales y un signo de menos para indicar los nmeros negativos. Al hacerlo, sin embargo, debermos conseguir que funcione correctamente y permitir que el usuario introduzca la coma o el signo de negativo slo una vez y en el lugar apropiado para ello. Piensa en todo lo que podra estar involucrado para en esto. Lea sobre las propiedades SelStart y SelLength del TextField. 9 Modica el cdigo para que sea:

If (Key >= "0") and (Key <= "9") then Return False Elseif Key = "," and InStr (Text, ",") = 0 then Return False Elseif Key = "-" and SelStart = 0 and Instr (Text, "-") = 0 then Return False Elseif Key >= Chr(28) and Key <= Chr(31) then//tecla de cursor Return False Elseif Key = Chr(8) then //tecla de borrado Return False Else Return True End if De este modo evitaremos que se pueda utilizar el signo de negacin o la coma en ms de una ocasin, y slo dejaremos que se pueda escribir el signo de negacin al principio. Ahora el TextField funciona correctamente, permitiendo que el usuario introduzca un nmero vlido pero nada ms. Una subclase adicional Nuestro siguiente objetivo consiste en crear una subclase d NumEdit que no permita al usuario introducir un nmero mayor del valor que se haya denido como mximo. 1 Crea una subclase de NumEdit denominada LimitNumEdit. Para ello puedes acceder al men contextual utilizando el botn secundario del ratn (o bien Control + clic en el Macintosh) sobre NumEdit en el Editor de Proyecto y seleccionar Nueva subclase en el men contextual. REALbasic crear una nueva subclase de NumEdit y le pondr CustomNumEdit como nombre. Utiliza el panel de Propiedades para cambiar su nombre por el de LimitNumEdit. 2 Abre el Editor de Cdigo correspondiente a LimiNumEdit, y advierte que no se encuentra el manejador de evento correspondiente a KeyDown. Ms sobre Eventos Una Denicin de Evento es una llamada de mtodo que queda conectada con un mtodo real en alguna parte. Al introducir cdigo en un manejador de evento se proporciona el mtodo real al que llamar el evento. Pero este slo se puede enganchar con un manejador de evento. En una cadena de subclases la ms alta en proporcionar un manejador de evento se traga dicho evento, y no permite que ninguna de las posteriores subclases puedan verlo. Sin embargo esto no representa un problema, dado que no hay nada que impida que la subclase que gestiona el evento de denir un nuevo evento adicional, que tenga exactamente el mismo nombre y argumentos del que est gestionando, y que llame a ste cuando lo considere oportuno. Veamos cmo podemos hacer esto. 1 Abre NumEdit y aade una nueva denicin de evento KeyDown, justo como el original (el mismo argumento y tipo devuelto). 2 Modica el manejador de evento KeyDown para que sea:

If (Key >= "0") and (Key <= "9") then Return KeyDown(Key) Elseif Key = "," and InStr (Text, ",") = 0 then Return KeyDown(Key) Elseif Key = "-" and SelStart = 0 and Instr (Text, "-") = 0 then Return KeyDown(Key) Elseif Key >= Chr(28) and Key <= Chr(31) then//tecla de cursor Return KeyDown(Key) Elseif Key = Chr(8) then Return KeyDown(Key) Else Return True End if De modo que en aquellas partes donde anterioremente estuvisemos permitiendo una tecla, ahora nos encargamos de pedir a nuestra subclase que decida qu debe hacerse con ella. Si no hay un manejador, entonces se devuelve el valor False por omisin, de modo que el comportamiento sea el mismo que era cuando no exista una subclase, o si dicha subclase no proporcionara un manejador para este evento. Pero si lo hace, entonces puedes restringir aun ms la aceptacin de las teclas pulsadas. Sin embargo advierte el modo en el que hemos congurado nuestros eventos y el modo en el que los llamamos no proporciona a la subclase una va para aceptar ms teclas. Si la superclase excluye una tecla, entonces la subclase no llegar a verla o recibirla para tratarla en su propio evento. 3 Comprueba que NumEdit aun funcione. 4 Cambia el TextField de la ventana a un control LimitNumEdit (haciendo clic en el TextField en la ventana y cambiando su Super en el panel de Propiedades), y prueba que an sigue funcionando. Dado que no hemos aadido nuevo cdigo, se comporta exactamente del mismo modo que hace su superclase. Piensa ahora en lo que necesitaramos para implementar un LimitNumEdit tal y como queremos que sea. Ahora hagmoslo. 5 Aade la propiedad Mximum a la clase LimitNumEdit, as como un motdo SetMaximum: Sub SetMaximum(M As Integer) Maximum = M Por lo general, no deberamos de denir directamente el valor de una propiedad, de modo que hemos creado este mtodo de asignacin para ello. 6 Aade el siguiente cdigo al manejador de evento KeyDown: Function KeyDown(Key As String) As Boolean Dim ChangedString As String

ChangedString = Left(Text, SelStart) + Key + Mid(Text, SelStart + SelLength + 1) If Val(ChangedString) <= Maximum then Return False Else Return True End if

Como de costumbre, consulta cualquiera de las funciones encargadas de tratar el texto, en el caso de que no ests seguro cul es su cometido. 7 Aade el siguiente cdigo al manejado de evento Open para el control de la ventana: Me.SetMaximum 500 8 Ejecuta el proyecto, y comprueba que funciona como est previsto. 9 Para propsitos de evaluacin, aade una nueva Denicin de Evento Boo a la clase NumEdit. Crea una nueva clase FurtherNum, utilizando LimitNumEdit como su Super. Advierte que FurtherNum tiene un manejador Boo. Esto es as porque LimitNumEdit no dene un manejador de evento para Boo (para que nuestra terminologa quede clara en este punto: no denir un manejador de evento signica que no hay cdigo en el manejador de evento). 10 Elimina ahora el Nuevo Evento Book de NumEdit y elimina su manejador antes de que guardes la versin nal del proyecto. Es posible que tambin desees Exportar las clases NumEdit y LimitNumEdit de la Ventana de Proyecto (seleccinalas y busca el comando Exportar en el men Archivo o en su men contextual). Estas son de hecho nuestras primeras clases tiles, y puede darse el caso de que las utilices algn da. As, slo tendrs que arrastrar los archivos en el Editor de Proyecto correspondiente a otro proyecto, de modo que puedas usarlas de nuevo. Asegrate de arrastrar NumEdit antes de hacerlo con LimitNumEdit. De lo contrario, no habr nada de lo que LimitNumEdit pueda ser una subclase cuando se importe, perdiendo por tanto el ajuste de su superclase. Ejercicios adicionales Intenta alguno de los siguientes ejercicios: Implementa una subclase PositiveNumEdit (para aceptar slo nmeros positivos); Utiliza la clase LimitNumEdit en un proyecto con una ventana que realice una operacin sobre los dos nmeros introducidos, mostrando su resultado en un tercer TextField; Lo mismo pero en este caso utilizando un grupo de botones de radio para seleccionar las operaciones; Lo mismo de nuevo, pero actualizando el resultado a medida que se vaya tecleando; Implementa la subclase RangeEdit, que dene un nuevo evento WithinRange, y que es llamado cuando se introduce un nmero comprendido en un rango determinado. Tambin necesitars denir las propiedades y los mtodos necesarios para denir el rango.

Explicaciones/Referencias: Los eventos estn explicados en el Captulo 5 de la Gua del Usuario de REALbasic (particularmente en la seccin Aadir Nuevos Eventos).

Leccin 12 Interfaces de Clase Objetivo En esta leccin examinaremos nuestra ltima caracterstica principal de POO en REALbasic: la Interfaz de Clase. La esencial del Tipo La nocin de tipo con la que hemos estado trabajando se resume en esto: un tipo es un nombre y un conjunto de operaciones (propiedades y mtodos). Dado que siempre podemos crear mtodos de obtencin (getter) y denicin (setter) para cualquiera de las propiedades que pueda requerir un tipo, la nocin ms sencilla posible a la que podemos llegar para un tipo es la de un nombre y un conjunto de deniciones de mtodo. (Ten en cuenta que por deniciones de mtodo, no queremos referirnos al cdigo real de los mtodos, sino solamente a sus nombres y argumentos4. Esto es precisamente en lo que consiste una interfaz: un nombre y un conjunto de deniciones de mtodo. Podemos crear un nuevo tipo mediante la creacin de una interfaz sobre la que asignaremos deniciones de mtodo. Podemos hacer una clase que tenga dicho tipo aadiendo el nombre del tipo en su propiedad de interfaces, y asegurndonos que soporte todos los mtodos denidos por la interfaz. Advierte que esta idea es diferente de la herencia. La herencia a partir de una superclase comn garantiza que dos clases tendrn los mismos mtodos y, por tanto, que tambin podrn ser tratadas como el mismo tipo. Pero la herencia va ms all del mnimo requerido, al proporcionar la implementacin de los mtodos junto con las propiedades. Otro modo de describir la diferencia entre una interfaz y una herencia de clase es as: una interfaz dene un tipo, pero la herencia tambin proporciona como mnimo parte de la implementacin. La cuestin obvia ahora es: Por qu no querramos una clase que tuviese como mnimo parte de la implementacin cuando la asignamos a un tipo? (incluso, por qu necesitamos este modo reducido de denir un tipo, despus de todo?) La respuesta es: nos evita muchas complicaciones cuando queremos que nuestro lenguaje de programacin nos permita que nuestras clases tengan ms de un tipo. Mltiples tipos A medida que empiezas a desarrollar programas ms complejos, no pasar mucho tiempo en que encuentres normal el hecho de querer que una clase tenga ms de un tipo. El ejemplo ms obvio son las clases suministradas: podramos querer que estas tuviesen papeles adicionales, y el modo natural de conseguirlo es proporcionndoles tipos polimrcos adicionales. En el programa que crearemos en esta leccin, ampliaremos el proyecto de contar palabras de modo que pueda mostrar el resultado tanto en un ListBox como en un TextField.

Otro nombre que oirs para esto es el de una rma de mtodo, declaracin de mtodo o signatura de mtodo.

El modo correcto de lograr esto en un lenguaje de programacin orientado a objeto como REALbasic consiste en proporcionar el mismo tipo a estas dos clases, de modo que podamos asignarles las operaciones adecuadas para que muestren el contador de palabras. Pero REALbasic slo nos permite asignar una superclase a una clase. La pregunta ms obvia ahoa es: Por qu no puede una clase tener mltiples superclases? Slo una Superclase Hay buenas razones para permitir slo una superclase para una clase dada. Los lenguajes de programacin que nos permiten tener ms de una superclase entran en una variedad de complicaciones. Por ejemplo, qu ocurre si las dos superclases tienen un mtodo o propiedad con el mismo nombre? Qu ocurre cuando las dos superclases tienen una superclase en comn? Figura 44. Una jerarqua de clase hipottica. (Captura Figura 44) En un lenguaje de programacin que soporte una herencia mltiple como esta, asume que Class1 tiene una propiedad Size. Esto signica que tanto Class2 como Class3 tienen una propiedad Size. Debera Class4 tener slo una propiedad Size, o dos (presumiblemente, tendramos algn modo de cambiar el nombre de una de ellas)? La respuesta es que depende: puede que quieras slo una propiedad, pero es posible que tambin puedas querer las dos. Hay otras complicaciones, como qu ocurrira con un mtodo de la clase Class1 que fuese modicado en Class2 pero no en Class3. Consideraciones como esta signican que los lenguajes de programacin que soportan la herencia mltiples son convulsos y dicultan por lo general los mecanismos de mantenimiento para controlar el modo en el que se comporta y realiza el proceso de herencia. Las interfaces evitan este problema, dado que no incorporan implementacin. Un Contador de Palabras muy mejorado 1 Abre el proyecto de la Leccin 9 (el contador de palabras que puede contar tanto a partir de archivos como desde el portapapeles). 2 Aade un TabPanel a Window1 (lee sobre el uso de los TabPanel en la Gua del Usuario). 3 Usa dos paneles con los nombres List y Text y pon el ListBox WordList sobre la primera pgina del TabPanel, de modo que la ventana tenga este aspecto: FIgura 45. Window1, mostrando el ListBox. (Captura Figura 45) 4 Aade un TextArea con el mombre WordLister a la segunda pgna del TabPanel.

5 Activa las propiedades MultiLine y ScrollBarVertical, de modo que esto sea lo que veas cuando cambies a la segunda pgina del TabPanel: Figura 46. Window1, mostrando el TextArea. (Captura Figura 46) Examina los mtodos y propiedades denidas en Window1 y considera por qu, teniendo en cuenta lo aprendido en anteriores lecciones, sera ms apropiado que gurasen en clases separadas. Piensa sobre la forma que podra tener dicha clase (necesitar todos los mtodos y propiedades denidas en Window1, para empezar...). 6 Crea una clase WordCountList, y mueve los mtodos y propiedades de Window1 a la nueva clase. 7 Aade una propiedad WordCounter As WordCountList a Window1. 8 Aade un manejador de evento Open a la ventana, con cdigo para inicializar WordCounter: WordCounter = New WordCountList 9 Abre el cdigo en cualquiera de los botones, y piensa sobre cmo deberas modicarlo para acomodarlo al nuevo objeto. Debera resultar sencillo cambiar las partes superiores del cdigo, pero surgir un problema interesante cuando consideres el modo de mostrar los resultados. Puede que te sientas tentado de aadir mtodos Get a la clase WordCountList, de modo que puedas iterar la lista de palabras y mostrar sus contenidos, tal y como venamos haciendo hasta ahora. Hacerlo sera un diseo pobre. Proporciona a los Objetos un comportamiento de nivel superior (o piensa dos veces sobre los Mtodos Accesorios) Esta parte es muy importante. Es un ejemplo del tipo de cosas que necesitas aprender para que seas un buen programador orientado a objetos. Debes pensar dos veces sobre cualquier diseo en el que se vean envueltos mtodos Get y Set (tambin conocidos como Mtodos Accesorios o Accessor Methods). Si bien resultan apropiados por lo general, deberas ver si existe una solucin de diseo mejor. Cualquiera de dichas soluciones involucra por lo general proporcionar mtodos de un nivel superior al objeto en el que ests tentado de aadir mtodos accesorios. Por nivel superior, queremos indicar algo as como ms sosticado o realizando una tarea ms amplia. El diseo actual es un ejemplo excelente de esto: el trabajo de mostrar el contador de palabras podra estar gestionado entre la clase WordCountClass que tendr el listado de las palabras, y la clase que ser la encargada de mostrar dicho listado.

Una versin ligeramente distinta de este diseo heurstico (que signica regla de oro) consiste en decir que el cdigo encargado de realizar la tarea debera encontrarse distribuido entre los objetos que deben encontrarse involucrados. Esta heurstica nos indica que el botn y la ventana no deberan de contener ninguna parte de la lgica relacionada con mostrar el contador. Esta regla permite mantener nuestro cdigo ms simple, dado que nos proporciona menos lugares en los que debamos mirar en busca de posibles problemas, al tiempo que hace que los objetos sean ms portables entre diferentes proyectos (o entre diferentes partes de un mismo proyecto). 1 Ahora que hemos tomado nuestra decisin sobre el diseo, este es el cdigo para el manejador de evento Action del botn correspondiente al Clipboard: //Ejecuta CountWords en el portapapeles, y copia a continuacin los resultados en WordList Dim Source As ClipBoardSource Source = New ClipboardSource WordCounter.CountWords(Source) WordList.clear WordCounter.Display WordList WordLister.clear WordCounter.Display WordLister Otro buen diseo habra consistido en que el mtodo Display ejecutase el mtodo clear; sin embargo, al separar dicha llamada, matenemos algo de exibilidad extra para, por ejemplo, mostrar el contador de palabras en varias etapas o a partir de varias fuentes. 2 Selecciona Proyecto > Aadir > Interfaz de clase5. Nmbralo WordCountDisplayer en el panel Propiedades. 3 Haz doble clic en la interfaz de clase en el Editor de Proyecto, y aade dos deniciones de mtodo: Sub Clear() y Sub Add(w As String, c As Integer) 4 Crea un mtodo con el nombre Display en la clase WordCountList: Sub Display(w As WordCountDisplayer) Dim counter As Integer w.Clear For counter = 0 to UBound(Word) w.Add Word(counter), Count(counter) Next 5 Crea una clase WordCountListBox, con ListBox como super.
5

Tambin puedes acceder al men contextual o hacer clic sobre la barra de herramientas de la pestaa Proyecto; selecciona Personalizar... y aade Interfaz de Clase a la barra de herramientas.

6 Haz clic en la propiedad Interfaces e introduce WordCountDisplayer. Implementa los mtodos Add y Clear correspondientes: Sub Add(w As String, c As Integer) AddRow str(c) Cell(ListCount - 1, 1) = w y Sub Clear() DeleteAllRows 7 Cambia el cdigo en el manejador de evento Action correspondiente a CountFileButton: //Solicita un archivo al usuario, y ejecuta a continuacin CountWords sobre dicho archivo, //copiando los resultados en WordList Dim counter As integer Dim Source As FileSource Dim f As FolderItem Dim s As BinaryStream Source = new FileSource //Solicita el archivo f=GetOpenFolderItem("application/text") If f<>Nil then s = f.OpenAsBinaryFile(False) Source.SetFile s WordCounter.CountWords(Source) WordList.clear WordCounter.Display WordList End if 8 Utiliza el panel de Propiedades para cambiar el ListBox a WordCountListBox. Antes de que procedas con las siguientes instrucciones, prueba a crear WordCountEditField por ti mismo. Tendrs que decidir cmo mostrar los resultados (quiz una palabra en cada lnea, teniendo en cuenta que cada lnea se lea algo as como manzanas: 3). Si necesitas ayuda, este es un modo de crear dichos mtodos para el WordCountEditField: Sub Add (w As String, c As Integer) If Text = "" then Text = Text + w + ": " + Str(c) Else Text =Text + Chr(13) + w + ": " + Str(c) End if Sub Clear() Text = ""

Es posible que tu cdigo sea distinto a este, y tambin puede que muestre los resultados de un modo algo distinto. Est bien, isempre y cuando funcione. No te olvides de aadir WordCountDisplayer a la propiedad de Interfaces para la clase, y de cambiar el EditField de la segunda pgina del TabPanel en Window1 para esta nueva clase. 9 Ejecuta el programa, y avanza a travs de las partes importantes en el caso de que no tengas claro cmo funciona. Preguntas y Conclusiones Las interfaces de clase son una herramienta importante para producir los mejores diseos de programa en REALbasic. Ahora tienes todas las herramientas que necesitas para simplicar y estructurar tu cdigo con eciencia utilizando el Polimorsmo, siempre que sea apropiado. Ejercicios adicionales Prueba a realizar alguno de los siguientes ejercicios: Aade una nueva clase WordCountDisplayerGroup al proyecto. Su tarea consiste en almacenar referencias a mltiples WordCountDisplayers y emitir llamadas a cada uno de los objetos a los que se reera. De modo que tambin es un WordCountDisplayer, pero tambin tiene un mtodo Add, con un argumento WordCountDisplayer. Los botones slo necesitan indicar al contador de palabras que se muestre a s mismo en el WordCountDisplayerGroup, y dicho objeto se encargar de pedir a cada uno de sus visualizadores que se encarguen de mostrar los contenidos. Aade la capacidad de mostrar un archivo delimitado por tabuladores. Esto debera funcionar correctamente con una tercera pestaa que te permitiese seleccionar el archivo de destino. Para escribirlo, necesitas investigar sobre cmo escribir un archivo. Comentario Final Ten en cuenta que la Gua del Usuario indica que las interfaces slo estn para usarlas con los controles, pero esto no es as: tambin son indicadas para otras situaciones con cualquier tipo de objeto. Deberes: Escribir a Archivo Tu tarea consiste en aadir un nuevo WordCountDisplayer al proyecto contador de palabras en el que estamos trabajando. Esta nueva clase escribir el contador de palabras a un archivo. Como mnimo tendrs que leer la seccin de la Gua del Usuario de REALbasic correspondiente a Obtener un Archivo en una Ubicacin Especca. Tambin deberas de leer Comprender los FolderItems y Trabajar con Archivos de Texto. El archivo de texto debera de encontrarse delimitado con rabuladores, lo que signica que cada palabra y su contador est escrito al archivo como la palabra seguida por un

tabulador, y seguida por el contador (como cadena), y seguida por ltimo con el caracter de retorno (ASCII 13). Deberas de escribir en primer lugar una clase que se encargase de enviar la informacin al archivo con un nombre determinado en el escritorio. Busca la funcin DesktopFolder en la referencia incorporada para obtener ms informacin y ejemplos sobre cmo utilizar esta funcin. Una vez que est funcionando, deberas modicarla de modo que pueda proporcionrsele una ruta o un folderitem (a tu eleccin) sobre el cual guardar la informacin. Deberas aadir un panel al TabPanel con un botn que permita al usuario crear el archivo que contendr la informacin. Deberas mostrar la ruta seleccionada en un EditField en el control de pestaa. Quiz quieras aadir un checkbox para activar o desactivar dicha exportacin. Echa un vistazo a GetSaveFolderItem para comprobar cmo puedes mostrar el cuadro de dilogo estndar correspondiente a guardar archivo. Tambin deberas echar un vistazo a la clase FolderItem para averiguar como puedes encontrar informacin como la ruta del FolderItem una vez que el usuario haya creado el archivo.

Leccin 13 Ordenacin por el mtodo de la Burbuja Objetivo Tomaremos un descanso de la programacin orientada a objetos para volver a los algoritmos. Durante las prximas lecciones examinaremos una serie de diferentes modos de ordenar una lista. Una vez examinado dicho cdigo y tcnicas habrs logrado lo siguiente: Empezars a aprender la rica y compleja nocin de eciencia en la programacind e ordenadores; Vers un ejemplo sobre la cantidad de modos que suelen encontrarse para solucionar un problema dado (incluso si aparentemente parece que slo haya uno) con un ordenador, y Vers algo ms de cdigo. Es importante leer una buena cantidad de cdigo. Sobre la eciencia Existen unas cuantas nociones especcas de eciencia en ciencias de la computacin, y las veremos en un momento. Pero antes de que lo hagamos, considermos la eciencia de un modo ms amplio. Tiempo del Programador frente a Tiempo del Usuario Comenzaremos observando que existens dos tiempos6 diferentes utilizados por un programa de ordenador: El tiempo del programador, utilizado en escribir el programa; y El tiempo del usuario, esperando a que el programa termine. El tiempo del programador es escaso A continuacin, consideremos que existen una serie de tareas que consumen el tiempo del programador: Hacer que un programa funcione correctamente; Hacer que un programa funcione ms rpido (o con menos memoria); Hacer que un programa se pueda cambiar con facilidad; Haciendo alguna otra cosa (escribiendo otro programa diferente; dar un paseo al perro; aprendiendo espaol...) (Las tres primeras no estn claramente separadas. Por ejemplo, hacer que el programa sea ms fcil de cambiar y hacer que sea correcto parece que vayan de la mano).

En realidad, hay potencialmente otros tipos de tiempo, y otros recursos escasos que probablemente queramos perservar: tiempo de transmisin en red, o tiempo para mostrar algo, o bien tiempo para mostrar el primer resultado derivado de una tarea compleja.

Nuestra segunda observacin, entonces es que, existen varias demandas sobre el tiempo del programador. En este punto tambin advertimos que la mayora de los programas slo se utilizarn durante un periodo de tiempo determinado, despus del cual se utilizar una nueva versin, o bien el programa dejar de utilizarse del todo. El tiempo del usuario, frente al tiempo del ordenador El tiempo del ordenador est siendo cada vez ms barato y a mayor velocidad. Mientras tanto, las personas trabajan a la misma velocidad a la que siempre lo han hecho. Cada vez con mayor frecuencia, cuando un usuario ejecuta un programa prcticamente todo el tiempo involucrado en el proceso consiste en que el usuario dena los datos, seleccione qu programa ejecutar, leer los resultados, etc. Por qu deberas escribir probablemente muchos programas sucios y rpidos Todo esto nos lleva a la conclusin de que una buen cantidad de programas deberan de ser escritos utilizando el cdigo ms sencillo y rpido posible. Tu tiempo probablemente sea ms escaso que el de tus usuarios. Incluso est bien si no se trata de un programa lento que termine en un segundo (quiz tu programa sea usado por un milln de personas), en comparacin con un programa rpido que termina en 1/100 de segundo. Escribiendo programas sencillos existen multitud de tareas sencillas que puedes evitar a las personas. Si haces muchas de estas, entonces la escritura de programas sucios y rpidos es una cuestin a tener en cuenta. Cuando deberas invertir ms tiempo escribiendo un programa Deberas pasar ms tiempo escribiendo un programa en los siguientes casos: El programa no funcionar en un instante si no prestas atencin a la velocidad del programa, y se utilizar con frecuencia o por muchas personas; El programa debe de encargarse de un problema de gran tamao (digamos echando una hora adicional escribiendo cdigo ms eciente se traduce en que el programa termina en unos pocos minutos en vez de en una semana; y como veremos este tipo de diferencia es sorprendentemente comn); El programa ser usado durante mucho tiempo. Probablemente se modique repetidamente, de modo que deberas invertir como mnimo el tiempo necesario para realizar su diseo y hacer que su modicacin resulte sencilla, adems de encontrarse bien documentado; Cuando la velocidad del cdigo se manieste a s misma como otro factor de calidad percibido por las personas, entonces tambin querrs optimizar la velocidad de tu cdigo. El ejemplo ms comn de esto se encuentra en los juegos: cuanto ms rpido se ejecute tu cdigo, ms imgenes podr generar por segundo, lo que signicar que la animacin ser ms suave. Probablemente puedas concebir otra serie de criterios adems de los expuestos.

No desperdicies tiempo en eciencia innecesaria Invertiremos algo de tiempo echando un vistazo a la nocin de eciencia en programacin tal y como la denen los propios programadores por lo general. A medida que lo hagamos, vers que con bastante frecuencia el cdigo que es ms fcil de escribir tambin correr con mayor lentitud (en algunos casos con mucha ms lentitud). No cometas el error en el que incurren de forma sorprendente muchos programadores, pensando que el cdigo ms lento y sencillo es malo. Con bastante frecuencia, se trata de un cdigo mejor, dado que lo escribes ms rpido y resulta ms sencillo de comprender. Las diferentes partes de un programa requieren de diferentes dosis de atencin Una observacin nal: incluso en un programa en el que decides invertir una buena cantidad de tiempo optimizndolo (lo que signica que consigues que funcione ms rpido en menos memoria), habr partes del programa donde no puedas hacer ms. Slo podrs optimizar las partes del programa en las que el ordenador emplee una gran cantidad de tiempo. Cuatro lecciones sobre Ordenar Ahora veamos la ms nocin ms breve sobre la eciencia. Uno de los libros ms famosos sobre programacin, The Art of Computer Programming, describe 29 modos diferentes de ordenar un listado de cosas (junto con algunas variaciones menores). Y el listado en dicho libro no es exhaustivo. En esta y las siguientes tres lecciones, veremos cuatro de estos modos de ordenacin. Examinaremos cmo funcionan, probaremos lo rpidos que son; consideraremos brevemente otros problemas, como por ejemplo cul sera el peor y mejor caso de rendimiento; y consideraramos variaciones menores sobre ellos con el objeto de mejorar su rendimiento. Ordenacin por el mtodo de la burbuja Comenzaremos con el mtodo de la burbuja, probablemente el que suponga el algoritmo de ordenacin ms sencillo, y tambin uno sorprendentemente ineciente. 1 Abre el proyecto BubbleSort y examina el cdigo del manejador de Evento SortEvent correspondiente a la clase BubbleSortList. 2 Pon un punto de parada en el comando Do. No hemos visto anteriormente el Do... Loop Until. Es justo como el bucle While... Wend, exceptuando que ejecuta el cuerpo del bucle una vez antes de probar la condicin, y entonces deja de ejecutar el bucle cuando la condicin se evala a True y no como False. Deberas probar a imaginar cmo se realiza la ordenacin examinando para ello el cdigo, antes de proceder a leer la explicacin en el siguiente prrafo. Cmo funciona la ordenacin por el mtodo de la burbuja

El mtodo de la burbuja funciona pasando por la lista de un extremo hasta el otro, examinando cada par de elementos adyacentes en la lista e intercambindolos en el caso de que no estn ordenados. Este procedimiento se repite hasta que se haya pasado de un extremo a otro de la lista sin haber intercambiado ninguno de sus elementos. Probablemente nunca se te haya ocurrido ordenar una lista de este modo, y es obvio lo ineciente que resulta. Pero el cdigo para implementar un Mtodo de Burbuja es muy simple. No tengas miedo de implementar un Mtodo de Burbuja si necesitas ordenar una pequea cantidad de informacin en un programa rpido y sucio. Por otra parte, en la siguiente leccin, veremos un algoritmo mucho ms eciente que es casi igual de sencillo de implementar (ordenacin por insercin). 1 Echa un vistazo al cdigo en el manejador de evento Accin correspondiente al botn Go. Ejecuta el programa y haz clic sobre el botn Go. Traza la ejecucin del cdigo examinando los contenidos del arreglo a medida que avances. Este programa se ha mantenido muy simple de forma deliberada. Se espera que ejecutes el programa en el depurador para que veas lo que hace, y si quieres ordenar una cantidad distinta de elementos, entonces tendrs que cambiar el cdigo en el botn. Todo esto se hace para mantener nuestra nocin de eciencia. Algunas veces es importante probar el cdigo para comprobar su eciencia, as como para comprobar su funcionamiento, pero si no pretendemos crear un programa nal o bien ests intentando ejecutar una serie de pruebas, entonces no merece la pena invertir mcuho tiempo haciendo que el test sea vistoso. Veremos ms sobre esto en las siguientes lecciones. Asegrate de que examinas el cdigo y ves como hemos usado el polimorsmo para separar la implementacin de la ordenacin frente al cdigo que solicita la ordenacin. El cdigo que solicita la ordenacin slo necesita saber que la cosa a ordenar es un NumList. Esto ser importante en futuras lecciones, donde ejecutaremos diferentes algoritmos de ordenacin y los compararemos. La Denicin de Eciencia ms Breve Dejando de lado toda nuestra discusin sobre la importancia de tu tiempo, es muy importante en ciencia de la computacin comprender el modo en el que vemos la eciencia. Hay varias situaciones donde ser importante escribir cdigo eciente. Existen varios tipos de eciencia, pero las dos ms importantes son: cuanto tiempo necesita un algoritmo para nalizar? y, cunta memoria necesita un algoritmo? El Mtodo de la Burbuja es muy bueno desde el punto de vista de su eciencia con la memoria: ms all de la propia lista de elementos, necesitamos un contador, una variable que se usar en el intercambio y un Booleano. Incluso se puede prescindir del contador (piensa sobre el modo de escribir el mtodo sin que sea preciso uno). Pero el cdigo es muy inecaz desde el punto de vista del tiempo. Prueba a aumentar la lista a 1.000 elementos y comprobars la cantidad de tiempo que requiere para nalizar. Cuando el tiempo para completar un algoritmo aumenta muy rpidamente con el tamao del problema (en este caso, el tamao del problema sera la cantidad de elementos en la lista), decimos que el algoritmo es inecaz en el tiempo.

Casos Mejor y Peor El mejor caso para este algoritmo es una lista ya ordenada. Bajo este supuesto, lo completar con la rapidez necesaria para comprobar que la lista ya est ordenada. Y una lista casi ordenada tambin terminar muy rpido tambin7 . El peor caso para el Mtodo de la Burbuja es cuando la lista est ordenada en orden inverso. En dicho caso, cada vez que se itere la lista se ordenar en su lugar uno de los elementos, y el resto de la lista permanecer sin cambios. En una lista de n elementos, un mtodo de la bubuja en el peor de los casos tendr que hacer n2 comparaciones (dado que busca una lista de n elementos n veces). Ejercicios adicionales A medida que observes el algoritmo en accin, y si piensas en lo que hace, observars que la primera vez que se ejecuta el bucle Do el elemento ms grande de la lista se pasa a la ltima posicin; la siguiente iteracin sobre la lista, el segundo elemento ms grande se pasa a la penltima posicin, etc. Como resultado de dicha observacin, considera cmo podra mejorarse el algoritmo. El algoritmo mejorado debera precisar slo n2-n comparaciones para una lista de n elementos. Una mejora razonablemenete sencilla del algoritmo consiste en crear pasadas alternativas a lo largo del listado en la direccin opuesta, con ello se mejora ligeramente el tiempo medio, y tambin mejora de forma palpable el peor de los casos. Resulta difcil llegar a una expresin matemtica simple sobre cuntas comparaciones se requieren en el peor caso, pero es considerablemente mejor que cualquiera de los anteriores.

Puede que existan ocasiones en las que escribirs un programa que deba tratar con esta situacin: necesitas ordenar una lista que est prcticamente ordenada. En este caso, el mtodo de la burbuja (o ms probablemente una ordenacin por insercin) sern ms rpidos que otros mtodos que veremos posteriormente.

Leccin 14 Ordenacin por Insercin Objetivo En esta leccin veremos otro algoritmo de ordenacin. Tambin crearemos un programa que nos permitir comparar con facilidad diferentes algoritmos de ordenacin. La ordenacin por insercin Comencemos considerando cmo ordenaras una pila de tarjetas que contuviesen un nombre sobre ellas. Probablemente pienses en utilizar una ordenacin por insercin: esencialmente, empezando con la primera tarjeta y creando una nueva pila de tarjetas donde cada una de las tarjetas ocupara la posicin correcta. A medida que cojes una tarjeta de la pila no ordenada encontraras su lugar en la nueva pila ordenada y la insertaras en ella. Esto es exactamente lo que queremos hacer en el ordenador. Piensa sobre cmo implementaras esto en el ordenador. Probablemente quieras mover los elementos de un arreglo en otro arreglo, imitando lo que haras con las tarjetas reales. Ahora pregntate si es posible implementar el mismo algoritmo utilizando slo un arreglo. Observa que no cambia la cantidad total de elementos involucrados en la lista ordenada y en la lista desordenada: a medida que una lista aumenta, la otra se reduce en una cantidad idntica. A partir de este punto, podemos deducir que es posible ordenar el arreglo en s mismo, creando para ello un arreglo ordenado a partir de uno de los extremos del arreglo desordenado. Esto ahorrar tiempo y memoria (ahorramos tiempo porque el ordenador no precisa alojar un nuevo arreglo), sin tener que hacer que el algoritmo sea signicativamente ms complejo. A medida que lo implementos vers que mover un elemento n a su posicin correcta involucrar rotar hacia bajo en uno la lista de elementos entre su nueva posicin y la antigua posicin; siendo el propio elemento ordenado el que se site sobre la seccin rotada del arreglo. De modo que parte del algoritmo ser una operacin rotar sub-arreglo. 1 Abre el proyecto InsertionSort. 2 Echa un vistazo rpido al proyecto Nos permite ejecutar ms de un algoritmo de ordenacin sobre la misma informacin y comparar el tiempo consumido por cada uno de los mltiples algoritmos. 3 Abre la clase InsertionSortList. Examina el mtodo Rotate. Bastante evidente. 4 Ahora examina el manejador de evento SortEvent.

Asegrate de que tambin compruebas la estructura general del proyecto, y observa cmo hemos usado las caractersticas de la programacin orientada a objetos para simplicar el diseo. 5 Ejecuta el proyecto y prueba con un ranto de valores interesante: 100 a 1.000 en pasos de 100 probablemente suponga un buen ajuste. Examina los resultados El siguiente paso es opcional, pero si te sientes cmodo con una hoja de clculo, entonces supone un buen modo de comparar los resultados. Una vez que se haya ejecutado el programa, este mostrar un TextArea con los tiempos obtenidos en cada uno de los dos algoritmos de ordenacin. Copia los valores desde el TextArea y pgalos en la hoja de clculo. Ordena la hoja de clculo por la primera columna, y corta a continuacin los valores de la columna de la derecha en la segunda mitad de las las a lo largo de la columna de la derecha y en la primera mitad de las, tal y como se ve aqu (los crculos muestran a partir de qu punto se han pegado los datos):
Bubble Sort Array Bubble Sort Array Bubble Sort Array Bubble Sort Array Bubble Sort Array Bubble Sort Array Bubble Sort Array Bubble Sort Array Bubble Sort Array Bubble Sort Array Insertion Sort Array Insertion Sort Array Insertion Sort Array Insertion Sort Array Insertion Sort Array Insertion Sort Array Insertion Sort Array Insertion Sort Array 100 200 300 400 500 600 700 800 900 1000 100 200 300 400 500 600 700 800 24 11

89 223 469 617 880 1060 1398 1766 2732 11 54 104 208 323 413 641 771

54 104 208 323 413 641 771 981 1248

Insertion Sort Array Insertion Sort Array

900 1000

981 1248

Ahora podras crear una grca a partir de las tres columnas de la derecha sobre la parte superior de las las, utilizando para ellos las tres primeras columnas como etiquetas, viendo de este modo el comportamiento de ambos algoritmos. Deberas de poder crear una hoja de clculo parecida a esta: Figura 47. Una hoja de clculo y una grca del resultado. (Captura Figura 47) El nuevo algoritmo es claramente mucho ms rpido; pero ten en cuenta que las dos curvas tienen el midmo tipo de forma (parablica). Esto signica que el nuevo algoritmo obtiene unos tiempos similares apra los conjuntos de datos que no son mucho mayores. Ambos algoritmos requieren de una buena cantidad de tiempo con conjuntos de datos de gran tamao. Pregntate en qu punto merece la pena el tiempo invertido por la ordenacin por insercin. La respuesta: rotando los elementos en la lista. Ejercicios adicionales En este momento sera interesante que te preguntases a ti mismo de qu modo podra mejorarse este algoritmo. Existen varias posibles respuestas a esta pregunta... Esta es slo una de ellas para ayudarte a empezar, y que deberas intentar implementar: es ineciente buscar el punto de insercin simplemente empezando por la parte superior de la lista y observando uno por uno a lo largo de la lista, dado que la lista ya est ordenada. En vez de ello, implementando una bsqueda binaria, empiezas buscando en la mitad de una lista que ya est ordenada, saltando a continuacin a la mitad de la primera o segunda mitad, y a continuacin a mitad de la primera o segunda mitad y as sucesivamente, hasta que hayas delimitado la ubicacin que ests buscando en quiz un mximo de cinco elementos, y cambiando a continuacin a la bsqueda lineal de uno a uno. Esto mejorar tu tiempo de ordenacin notablemente.

Leccin 15 Redenir la Ordenacin por Insercin Objetivo En esta leccin veremos una variacin de la ordenacin por insercin. Crearemos un framework que nos permite comparar la velocidad de diferentes algoritmos de ordenacin, y lo utilizaremos para ver si la nueva variacin es ms rpida. Sobre las Pruebas Con frecuencia resulta til realizar pruebas para comparar la velocidad de los algoritmos. En muchos casos no resulta fcil pobar si uno de ellos es ms rpido que el otro o bien cundo es ms rpido. Un lenguaje de alto nivel como REALbasic introduce otra complicacin: REALbasic hace varias cosas por nosotros entre bambalinas, y no sabemos exactamente cmo hace dichas cosas, o cundo las hace. Por ejemplo, a medida que creamos y destruimos las variables o bien cambiamos el tamao de los arreglos o las cadenas, REALbasic est realizando por nosotros las cuestiones relacionadas con la gestin de memoria (siguiendo las variables usadas en cada sitio, el tamao de cada una de ellas, y reclamando el espacio ocupado por las variables destruidas o cuyo tamao ha sido modicado). En algunas ocasiones, la actividad que REALbasic est haciendo entre bambalinas introducir algunas incertidumbres o imprediccin en el tiempo requerido por el algoritmo o bien una parte de este para su nalizacin. Como vers en esta leccin, slo porque sintamos que algo debe ser ms rpido no signica que realmente vaya a ser as... Varias formas de mejorar la Ordenacin por Insercin Al nal de la ltima leccin, te pedimos que pensaras en formas de mejorar el algoritmo correspondiente a la ordenacin por insercin. Existen varias posibles respuestas para esto. Estas son unas cuantas: Asumiendo que los valores a ordenar estn distribuidos de forma aleatoria, empieza buscando por un punto de insercin cuyo valor de ndice est estimado a partir del valor que se insertar (de modo que si hay 100 elementos en la lista, con valores hasta 100, comienza buscando el punto en el que insertar el valor de 50 en la mitad de los valores ordenados ms alejados, y empieza a buscar sobre dnde insertar el valor 25 dentro del primer cuarto del listado); Realiza una bsqueda binaria para el punto de insercin (busca en el valor medio, y a continuacin la mitad d ela lista por encima o por debajo de dicho punto, y a continuacin en la mitad de los valores restantes, etc). Ordena en N listas independientes, cada una de las cuales se encarga de un rango concreto de valores, y mezcla a continuacin dichas listas al nalizar; y En vez de rotar los elementos en el arreglo donde se insertar el valor, mantiene una lista de los siguientes valores del ndice en un arreglo paralelo, y averigua el orden correcto empleando dicho arreglo. Esto hace que la insercin utilice un nmero jo de

operaciones, en vez de que requiera una cantidad de tiempo mayor a medida que la lista tambin se hace ms grande. Por supuesto tambin es posible combinar algunas de estas dieas. Probaremos la ltima idea. Parece que fuese la ms rpida, dado que la asignacin de un par de elementos de arreglo debera de resultar considerablemente ms rpido que la mayor cantidad de asignaciones involucradas en la operacin de rotacin sobre un listado de gran tamao. 1 Abre el proyecto 15_InsertionSort2. Ejectalo para un ranto de 100 a 1.000 en pasos de 100. Es probable que quieras copiar los resultados en una hoja de clculo y crear una grca de estos. Es probable que encuentres que este nuevo algoritmo no es ms rpido (fue ms rpido para 900 elementos o ms en un PowerBook G3/333 bajo Mac OS 9, pero ms lento para cualquier cantidad de elementos en el mismo ordenador bajo Mac OS X). Parece razonable esperar que el nuevo algoritmo ser ms rpido, de modo que este resultado es interesante (y demuestra por qu deberamos comprobar nuestras ideas preconcebidas). Despus de la operacin de ordenacin, un elemento del arreglo enlazado contiene el valor del ndice del elemento en el arreglo Numbers y que va a continuacin del elemento del arreglo de valores en el mismo ndice. Esto resulta ms sencillo de ver que de explicar, de modo que he aqu un ejemplo: ndice 1 2 3 4 5 6 7 5 5 1 3 4 2 4 Numbers 2 -1 6 5 7 4 1 Arreglo Link

El arreglo link nos indica qu la viene a continuacin. Mantenemos un seguimiento por separado del elemento ms bajo que debe ordenarse en el arreglo, de modo que ahora sabemos que la la 3 va en primer lugar (contiene el valor ms bajo, de 1). Miraremos a continuacin en el arreglo Link en la la 3, y esta nos indica que la la 6 es la siguiente (dado que tiene el siguiente valor ms bajo, de 2). Esta va seguida por la la 4, y as con el resto. La ltima dila, nmero 2, tiene un valor para el arreglo Link de -1, para indicarnos que no hay un elemento siguiente. Para insertar una la en la lista, es una simple cuestin de actualizar los valores enlazados de los elementos que le preceden y suceden en oden. Parece razonable

esperar eso para los arreglos de gran tamao, debera resultar ms rpido saltar simplemente a un elemento del arreglo de enlace, en vez de tener que rotar una gran parte del listado. Incluso si este mtodo es ms rpido, la simple construccin del arreglo de enlace no es lo mismo que ordenar el arreglo original. Buscar en el arreglo de una forma ordenada ser ms lento si es necesario seguir el arreglo enlazado hasta encontrar el siguiente elemento. Y encontrar el ensimo elemento en orden ser muy lento. Esta es una situacin comn: el algoritmo ms adecuado depende en muchas ocasiones de cmo queramos utilizar los resultados. 2 Abre la clase LinkInsertionSortList, y examina el manejado de evento SortEvent. Como ejemplo, aqu estamos haciendo todo en un mtodo de gran tamao dado que hacer todo mediante la llamada a un motdo en vez de en la posicin actual resulta un poco ms lento. Esto puede resultar de importancia cuando mulitplicas esa pequea diferencia por una gran cantidad de repeticiones a lo largo del bucle. Recuerda nuestras discusiones sobre la eciencia. Nos interesara hacer esto si redundase en un cdigo notablemente ms rpido; el retardo singicara que el alguien debiese esperar, y no tuvisemos algo ms importante en lo que invertir nuestro tiempo de programacin. Comentar y descomentar el Cdigo Hay tres modos de indicar que algo escrito en REALbasic es un comentario. Dos de ellos consisten en comenzar una lnea con // y comenzar la lnea con . Deberas usar siempre // para los comentarios reales, dado que existe una diferencia en el uso del estilo de comentario : REALbasic proporciona un botn Comentar/Descomentar en la barra de herramientas del Editor de Cdigo. Este aadir o eliminar la marca de comentario de un bloque de lneas. Puedes utilizarlo para desactivar o activar temporalmente una porcin de cdigo, lo que puede resultar de gran utilidad durante las tareas de depuracin. Si siempre utilizas las dobles barras inclinadas prara tus comentarios, entonces los comandos incorporados de Comentar/Descomentar no interferirn con tus comentarios reales. El manejador de evento LinkInsertionSortList tiene parte del cdigo comentado de esta forma hacia el nal. Este utiliza el arreglo de enlace para ordenar el arreglo (de modo que no se ralentice el acceso a un elemento concreto del arreglo ordenado). Si obtuviste resultados ms rpidos para el nuevo algoritmo, prueba de nuevo eliminando previamente los comentarios. El nuevo algoritmo debera de resultar ahora ms rpido, si bien el umbral sobre el que se apreciar su mayor velocidad se situa en una cantidad mucho mayor para la lista. Por qu es ms lento el nuevo algoritmo? Resulta difcil estar seguro por qu el nuevo algoritmo no puede ser ms rpido, pero podemos hacer algunas deducciones. En primer lugar, el nuevo algoritmo ha de hacer ms trabajo para empezar. El nuevo algoritmo debe de modicar el tamao de dos arreglos en vez de simplemente uno.

Ten en cuenta tambin que para cada comparacin de dos elementos del arreglo que estamos ordenando, el nuevo algoritmo ha de ejecutar dos comparaciones ms de lo que requiere el primer algoritmo. De modo que encontrar la posicin en la que debe insertarse el nuevo elemento se hace ms lento en comparacin con el primer algoritmo. Tambin ha de mantener el seguimiento de dos variables adicionales a medida que busca en la lista. Ejercicios adicionales Sera interesante implementar algunas de las otras ideas sobre cmo acelerar la ordenacin por insercin. Crea cada una de ellas como una clase independiente, y conctalas con el framework de pruebas de modo que puedas comprobar cul es la ms rpida con listados grandes. Sera sorprendente si alguna de las otras ideas sobre el modo de mejoar el algoritmo no fuesen realmente ms rpida. Dichos experimentos slo constituyen un ejercicio acadmico (si bien un buen ejercicio). En la prxima leccin probaremos un algoritmo distinto denominado Ordenacin Rpida y que es mucho ms rpido para una lista aleatoria...

Leccin 16 Ordenacin Rpida Objetivo En esta leccin veremos la ordenacin rpida (Quicksort) uno de los algoritmos ms rpidos para la ordenacin de propsito general. Aprenderemos como funciona, lo codicaremos en REALbasic y lo compararemos con los otros algoritmos de ordenacin que hemos desarrollado. Cmo funciona la ordenacin rpida Comenzaremos moviendo el primer elemento de la lista a la posicin nal, en el mismo proceso haciendo que todos los elementos en cualquiera de los lado sean todos los bajos (a la izquierda) y los altos (en la derecha). Comenzaremos comparando el primer elemento con el elemento situado junto a l, y el elemento que est al nal de la lista: Figura 48. La situacin inical. (Captura Figura 48) Moveremos x a la derecha e y a la izquierda, hasta que x apunte a un elmeneto mayor que 5 e y apunte a un elemento inferior a 5. A continuacin intercambiaremos los elementos a los que estn apuntando x e y: Figura 49. El primer intercambio. (Captura Figura 49) Repite este proceso, moviendo x e y hacia otros a medida que avanzamos: Figura 50. Otro intercambio posterior. (Captura Figura 50) Este proceso contina hasta que xy. Entonces intercambiamos el primer elemento (5) con el elemento situado en la posicin anterior a x: Figura 51. Completando la primera pasada. (Captura Figura 51) Hemos terminado? El 5 est ahora en la posicin nal, y las sublistas a ambos lados del 5 son inferiores en todos los casos (a su izquierda) o bien superiores a 5 (en su derecha): Figura 52. Hemos reducido el problema a dos problemas ms pequeos. (Captura Figura 52)

Deberas de ver que ahora simplemente podemos emplear el mismo proceso de forma recurrente para ordenar ambas listas ms pequeas. El Proyecto Abre el proyecto 16_QuickSort. Abre SortWindow en su Editor de Ventana, haz doble clic sobre el botn Quicksort, dene un punto de parada al nal del manejador de evento Action, y traza el algoritmo durante algn tiempo. 1 Ejecuta el antiguo botn de ordenacin sobre un rango interesante: quiz de 500 a 1.000 en pasos de 100. En el ordenador del autor, el algoritmo Quicksort fue en torno a 40 veces ms rpido en comparacin con la ordenacin por insercin... 2 Ahora prubalo de nuevo con nmeros ms pequeos. Es posible que Quicksort sea incluso ms lento para algunas listas pequeas. Ejercicios Adicionales Puede hacerse que el algoritmo sea ms rpido. El algoritmo Qucksort es bastante ineciente con listas pequeas. Lo que funcionara mejor sera cambiar a otro algoritmo como a la ordenacin por insercin para las listas pequeas. Ten en cuenta que una lista de mayor tamao quedar reducida a varias listas ms pequeas hacia el nal del proceso, de modo que ordenar estas listas ms pequeas de una forma ms rpida acelerar considerablemente el proceso. Un gran ejercicio sera el de producir un programa que pudiese averiguar a qu tamao de listado debera cambiarse a un algoritmo de ordenacin diferente. Este podra ser un programa que midiese repetidamente la ordenacin de un gran arreglo, aumentando el tamao del listado ordenado mediante insercin, hasta que el tiempo comenzase a ser inferior.

Leccin 17 Excepciones, Constructores, Sobrecarga Objetivo Tomaremos un respiro de los algoritmos complejos. Echaremos un vistazo a un asunto de envergadura (Excepciones) y, de paso, tambin veremos algunas cuestiones adicionales (Constructores y Sobrecarga). Excepciones La gestin de errores y otras situaciones inusuales con los mecanismos de control que hemos visto hasta ahora (bucles, condicionales if-then, y otros similares) pueden hacer que el cdigo ms simple termine siendo ms complejo, dado que tienes que plagar el cdigo con comprobaciones para cada uno de los posibles errores que puedan tener lugar o bien condiciones atpicas. Esto puede hacer que el cdigo resulte ms difcil de desarrollar y tambin de mantener. Las Excepciones suponen una respuesta elegante a este problema, proporcionando un modo controlado de saltar fuera del actual ujo de control. He aqu un ejemplo. Pongamos por caso que este sea el ujo de control normal en alguna parte de un programa (El Mtodo A llama al Mtodo B que llama... al Mtodo D y vuelve al Mtodo C...): Figura 53. El ujo de control normal. (Captura Figura 53) Ahora, que hacemos cuando...? Figura 54. Tiene lugar un problema... (Captura Figura 54) Ocurre un problema aqu? Este problema puede ser un error en tu cdigo, o quiz pueda tratarse de algo fuera de tu control (quiz estuvisemos a punto de abrir un archivo, pero ha sido borrado desde la ltima vez que lo comprobamos). Continuemos con el ejemplo. En este caso, el error tiene lugar cuando intentamos accede al elemento de un ndice que no existe. En REALbasic dicha accin lanza una excepcin: Dim A(4) As integer A(5) = 7 ...y el cdigo salta desde donde se estuviese ejecutando al manejador ms cercano. Cuando se lanza una excepcin, REALbasic sigue un ujo de control muy distinto en comparacin con la ejecucin lnea a lnea. Busca el Manejador de Excepcin coincidente ms prximo. Este puede encontrarse al nal del mtodo en curso...

ReadElizaLine InputFrom, ElDelimiter, RespDelimiter Wend InputFrom.Close Exception E As OutOfBoundsException MsgBox Ese valor est fuera de rango. Quit ...o en el primer mtodo que contenga dicho manejador, comenzando desde la parte inferior de la actual cadena de llamadas, y continuando hacia arriba por dicha cadena: El Mtodo A llama a... El Mtodo B llama a... El Mtodo C llama a... El Mtodo D

Las excepciones se lanzan automticamente cuando va algo mal: Dim A As MyObject A.MyMethod Oops, A aun es Nil en este punto. Esto supone una execpin del tipo NilObjectException. ...o bien puedes lanzar una excepcin t mismo: Raise New NilObjectException

Aunque probablemente no quieras lanzar una NilObjectException de forma deliberada. Incluso puedes inventarte tus propias excepciones, y que son simplemente subclases de la clase RuntimeException. Puedes aadir tus propios mtodos y propiedades en ellas, tal y como haras con cualquier clase, y lanzarla cuando quieras tratar con alguna circunstancia inusual: Raise New MyExcepcion (Ests de broma.) (El argumento del Nuevo comando en este caso forma parte de un constructor, algo que aprenderemos en un momento). Es importante darse cuenta de que las Excepciones son objetos, teniendo una clase, con todos sus detalles: Pueden formar parte de una jerarqua de clase. Los manejadores pueden atrapar las excepciones de superclases o subclases; Puedes aadir mtodos y propiedades a ellos; Pueden incorporar mensajes de error y otra informacin; y Pueden realizar una accin Un manejador de execpcin puede atrapar todas las excepciones: Exception

... O puede recibir el objeto de excepcin como argumento: Execption E ... Y tambin puede atrapar la excepcin slo si es de un tipo concreto: Exception E As NilObjectException ... Puedes tener mltiples manejadores de excepcin al nal de un mtodo. Este ejemplo proporciona manejadores especcos para dos excepciones en particular, y a continuacin un manejador general que atrapar cualquier otro tipo de excepcin: Exception E As NilObjectException ... Exception E As OutOfBoundsException ... Exception ... Cuando existen mltiples manejadores como este, se ejecutar la excepcin coincidente que est ms prxima a la parte superior del cdigo. Los anteriores manejadores de excepcin ocurren al nal de los mtodos en los que tienen lugar. Tambin puedes crear un bloque manejador de excepcin en cualquier parte de un mtodo, utilizando para ello la construccin Try-Catch-Finally-End Try, y que tiene el siguiente aspecto: ... Try ... Catch ... End Try ... Esto sera equivalente al primero de los anteriores ejemplos, dado que atrapa todas las excepciones que ocurren entre el Try y el Catch. Tambin puedes recoger la excepcin propiamente dicha en una variable: ... Try ... Catch E ... End Try ...

Y puedes atrapar slo las excepciones de un tipo concreto: ... Try ... Catch E As NilObjectException ... End Try ... Otra opcin que tienes con este tipo de bloques consiste en proporcionar el cdigo que debe ejecutarse despus del bloque Try, tanto si se produce una excepcin como si no. Este utiliza la seccin Finally: ... Try ... Catch E As NilObjectException ... Finally ... End Try ... Siempre deberas de pensar sobre cualquier cosa de la que el bloque Try-Catch debiera de asegurarse despus de que haya nalizado (por ejemplo, debe cerrar cualquier archivo que hubiese abierto), y situarlo en el bloque Finally. Ten en cuenta que a diferencia del bloque Exception, puedes tener bloques Try-Catch anidados (lo que signica tener bloques Try-Catch dentro de otros bloques Try-Catch). Manejador de Excepcin por omisin Si la excepcin producida no encuentra ningn manejador coincidente, entonces REALbasic proporciona un manejador por omisin: En el IDE, REALbasic marcar la lnea en la que se ha producido la excepcin, y mostrar un mensaje sobre el tipo de excepcin que se ha producido (probablemente ya lo hayas visto en varias ocasiones): Figura 55. Manejador de Excepcin por omisin en el IDE. (Captura Figura 55) Si compilas tu programa y lo ejecutas fuera del entorno de desarrollo (que por lo general ser tu objetivo), entonces cuando se produzca una excepcin REALbasic mostrar un mensaje de error y saldr: Figura 56. Manejador de Excepcin por omisin en una aplicacin compilada. (Captura Figura 56)

Seguramente quieras evitar que REALbasic muestre un mensaje como este, de modo que es muy importante aprender a manejar las Excepciones. REALbasic proporciona un modo adicional de manejar las excepciones: una excepcin que no se gestiona en ninguna otra parte producir un evento UnhandledException en App. Siempre deberas proporcionar un manejador de este tipo en una aplicacin que proporciones a otro, de modo que utilice una forma ms elegante de tratar las excepciones no gestionadas frente al dilogo mostrado por REALbasic. Lo visto hasta ahora ha supuesto un primer vistazo sobre las Excepciones; ahora las examinaremos en accin. La Excepcional Eliza 1 Abre el proyecto incluyido, Exceptional Eliza. Vamos a hacer que la rutina de parseado 8 de Eliza pueda gestionar varios errores en el archivo. Mediante el uso de las Excepciones, podremos mantener prcticamente intactas las rutinas normales de parseado, al tiempo que incorporaremos un comportamiento muy distinto en las circunstancias excepcionales. 2 Examina la clase File Parse Error Advierte que est pensada como superclase abstracta (no hace nada por s misma; cuando llamas a su mtodo Announce slo estar realmente gestionado en la subclase como evento). 3 Examina la clase NaughtyWordError Fjate en concreto en el mtodo NaughtyWordError. Se trata de un mtodo especial denominado constructor. Constructores y Destructores Un constructor es simplemente un mtodo con el nombre Constructor o, com en este caso, con el mismo nombre de la clase. Cualquiera de estos mtodos se ejecutar automticamente durante la creacin de un objeto de ese tipo. Ten en cuenta que un constructor puede tener argumentos, y que puedes proporcionar como argumentos mediante el comando New (tal y como hicimos anteriormente). Tambin puedes tener un destructor, y que se ejecuta cuando un objeto deje de estar referenciado por cualquier variable (y que no seguir existiendo por ninguna otra razn; una Window (ventana) es un ejemplo de algo que continuar existiendo incluso en en el caso de que nada ms haga referencia a ella), de modo que REALbasic pueda reclamar el espacio que ocupe en memoria. Antes de que lo haga, llamar al destructor del objeto en el caso de que exista uno, de modo que puedas hacer cualquier tarea de limpieza que desees en tu objeto, en el caso de que sea neceario. Un destructor es un mtodo que no tiene parmetros y tampoco tipo devuelto, y que tienen el nombre Destructor.

El parseado consiste en tomar una cadena para extraer de ella la informacin estructurada. Los humanos lo hacemos cuando comprendemos una frase en espaol, y los ordenadores lo hace con los archivos.

Ten en cuenta que desde el punto de vista tcnico, los constructores y los destructores no son necesarios. Puedes escribir cualquier tipo de programa sin tener que utilizarlos. Pero resulta una buena idea utilizar un constructor en cualquier clase donde resulte apropiado, dado que contribuye a evitar que se cometan muchos errores. Examina la clase InvalidLineError Observa en concreto los dos constructores. El uso de dos o ms mtodos o funciones con el mismo nombre se denomina sobrecarga (overloading) del mtodo. Sobrecarga (Overloading) Podemos tener ms de un mtodo o funcin con el mismo nombre, siempre y cuando como mnimo uno de sus argumentos sea de un tipo distinto, o bien no tengan la misma cantidad de argumentos. Ten en cuenta que REALbasic slo podr elegir una versin del mtodo de cualquier llamada en particular, dado que los argumentos slo se correspondern con una verin. La sobrecarga es particularmente comn en los constructores, pero deberas sentirte libre de utilizar la sobrecarga siempre que sea razonable (en las siguientes lecciones veremos una amplia variedad de ejemplos correspondientes a la sobrecarga). Ten en cuenta que en el caso de los constructores, la sobrecarga es simplemente una cuestin de conveniencia. No representara una gran diferencia el hecho de tener mtodos con diferentes nombres. Pero deberas de utilizar la sobrecarga cuando tengas diferentes formas de solicitar una misma operacin sobre diferentes tipos o cantidad de argumentos. Lmites de la Sobrecarga El compilador actual de REALbasic tiene dos limitaciones relacionados con la sobrecarga y que deberas de tener presentes: Una clase y su subclase no se consideran de diferente tipo cuando se evala entre versiones de un mtodo sobrecargado. De modo que si Thing es una superclase de SubThing, entonces no habr diferencia alguna entre las siguientes deniciones de mtodo: Sub MyMethod(t As Thing) End Sub Sub MyMethod(t As SubThing) End Sub REALbasic busca una correspondencia para la llamada de un motod a travs de la jerarqua de la clase; y si un mtodo est denido en una clase, no ver una versin diferente de dicho mtodo denido en su superclase. La solucin consiste en sobreescribir el mtodo de la superclase en la subclase y realizar desde este de nuevo una llamada explcita al mtodo de la superclase. En una leccin posterior veremos cmo realizar una llamada al mtodo de una superclase. Echa un vistazo a StringList. Se trata de cosas que ya hemos visto anteriormente.

Examina el mdulo BadThings. Una caracterstica de los mdulos que no hemos visto anteriormente es que pueden incluir constantes, y que son como variables cuyos valores no se pueden modicar. Es buena idea utilizar constantes asignadas a nombres como en este caso para cualquier tipo de valor jo que vaya a utilizar tu programa, dado que de este modo slo tendrs que cambiar el valor en un nico sitio. En este caso, se encarga de contener una lista de las palabras indebidas que no puedes tener en el archivo de respuestas. Examinemos ahora los cambios en la clase StringResponder. Advierte que el cdigo encargado de parsear una lnea se ha movido a un mtodo distinto, ReadElizaLine. Haz doble clic sobre el nombre del mtodo en el panel de la izquierda del editor de cdigo, y advierte que el mtodo est declarado como Protected (protegido). Mtodos Privados Algunos mtodos formarn parte de la interfaz pblica de una clase. Estas son las operaciones que dene el Tipo de Dato Abstracto que implementa la clase (recuerda: un tipo est denido por lo que hace), y pueden ser llamados desde otras clases. Otros mtodos de una clase sern parte de las operaciones internas de dicha clase, y por tanto no estn destinados a que puedan ser llamados desde fuera de la clase. ReadElizaLine es un buen ejemplo de este tipo de mtodo. Haciendo que el mtodo sea Privado indica que el mtodo no forma parte de la interfaz pblica de la clase. Cuando un mtodo es Privado, el compilador hace que sea posible llamar a dicho mtodo desde fuera de la clase. De igual modo, las subclases de la clase no heredan el mtodo. Otra alternativa es el mtodo Protegido (Protected). Al igual que los mtodos Privados, los mtodos Protegidos no pueden ser accedidos desde fuera de la clase, pero las subclases de la clase s pueden heredar los mtodos Protegidos. De vuelta a las Excepciones Ten en cuenta que los comandos Raise generan el objeto justo en el comando, y cmo se pasan los argumentos a los constructores de la clase. Advierte tambin que New se est comportando ahora obviamente como una funcin. Observa las ubicaciones de los comandos Raise y los manejadores de mtodo (utiliza el rea Buscar en la barra de herramientas principal para encontrar estas llamadas). Observa que tenemos un manejador tanto para la clase base FileParserError (en LoadFromFile) como en la subclase NaughtyWordError en ReadElizaLine. Abre el archivo Responses.txt y observa si puedes encontrar dos posiciones en las que tendra lugar las excepciones. 1 Ejecuta el proyecto, activa puntos de parada en todos los lugares en los que puede producirse una excepcin, y avanza paso a paso para ver qu ocurre en cada caso.

Observa que la excepcin correspondiente al manejador NaughtyWordError (en el mtodo ReadElizaLine) provoca que el proyecto salte la lnea, para continuar parseando el archivo. Por otra parte, el punto de parada correspondiente a FileParseError (en LoadFromFile) aborta el proceso de parseado. Activa el comentario para el comando Quit en el manejador FileParseError para hacer que esto sea an ms claro. 2 Activa el comentario para el manejador NaughtyWordError, y observa el comportamiento cuando el proyecto est en funcionamiento. 3 Despus de haber comentado el manejador NaughtyWordError, mueve el manejador FileParseError al mtodo ReadElizaLine, pero eliminando el comando Quit. Comprueba qu ocurre ahora cuando tiene lugar el error. Ejercicios Adicionales Si comentas todos los comandos Quit en todos los manejadores de excepciones y ejecutas el programa, mostrar un par de alertas funcionando a continuacin. Pero prueba a introducir una frase que no se corresponda con ninguna de las respuestas enlatadas (de modo que deba obtener una respuesta aleatoria; un buen ejemplo podra ser Hola). El programa saldr con una excepcin OutOfBoundsException. Puedes solucionar este problema arreglando el archivo Responses.txt, pero tambin deberas de lograr que el programa gestionase mejor este problema. Aade el manejador correspondiente a OutofBoundsException. Otro ejercicio interesante sera dejar que las Excepciones se registrasen a s mismas (digamos en una clase ExceptionLog), y que se aadiesen al nal del proceso de parseado, antes de que el proyecto avanzase. En el caso de que no resulte obvio, el mejor sitio para registrar la generacin de un objeto sera en su constructor...

Leccin 18 Enumerador de Archivos Objetivo Tomaremos un respiro del aprendizaje de nuevos conceptos y cogeremos algunos de ellos para ponerlos en prctica en un proyecto til. Una clase til: un Enumerador de archivos Hemos absorbido una buena cantidad de conceptos durante el curso. Pasemos a utilizar dichas caractersticas para disear una clase muy til. Esta ser un enumerador de archivos exible. Enumerar es un trmino informtico que se reere a pasar por un conjunto de cosas una a una (un trmino similar con el que tambin puedes encontrarte es atravesar). Crearemos una clase con la que puedas referirte a una carpeta o archivo, y nuestra clase generar un evento para cada elemento de dicha carpeta. Aspectos del diseo Existen unas cuantas formas de enfocar lo que queremos llevar a cabo en este proyecto: Podemos crear una clase que atraviese parte del rbol de archivos, proporcionando una a su subclase la oportunidad de procesar cada archivo a medida que lo vaya haciendo; o Podemos crear una clase que llame de forma repetida a una clase receptor de archivo a medida que atraviesa el rbol de archivos; o Podemos hacer que la clase se pasiva, dirigida por llamadas repetidas desde el exterior, en las que se solicite el siguiente archivo. El enfoque que utilizaremos ser el primero; si quisiramos, podemos ampliarlo para crear la segunda. El tercer enfoque tiende a ser ms problemtico dado que el llamante externo necesitara comprobar el estado del recorrido de los archivos, comprobando por ejemplo si se ha nalizado dicho recorrido. Antes de que nos pongamos a ello, deberas leer acerca de la clase FolderItem. Profundidad frente a Anchura Los archivos estn dispuestos en una estructura de rbol compuesta por carpetas, subcarpetas, sub-subcarpetas, etc. Las Clases tambin son una forma parecida de rbol compuesto por clases, subclases, sub-subclases, etc. Las estructuras de rbol para almacenar la informacin son algo muy comn en la programacin de ordenadores, y su acceso requiere con frecuencia la enumeracin de sus contenidos tal y como haremos en este proyecto. Existen principalmente dos formas de recorrer una estructura de rbol: En un recorrido de profundidad en primer lugar, donde cada vez que encontremos una carpeta dentro de la carpeta actual, comenzaremos a enumerar de inmediato sus contenidos, tal y como haremos tambin cuando encontremos la primera carpeta dentro de dicha carpeta, etc. Regresaremos al resto de los elementos de una carpeta despus de que hayamos enumerado los contenidos de su subcarpeta; o

En un recorrido de anchura en primer lugar, enumeramos todos los archivos de la carpeta actual, enumerando a continuacin los contenidos de cualquier carpeta que encontremos dentro de la actual. Veremos ambas tcnicas en accesin durante el proyecto de esta leccin. El Proyecto 1 Abre el proyecto 18_FileEnumerator. Abre la clase FileEnumerator. Observa que la clase tiene un constructor, un mtodo pblico, varios mtodos privados y tres eventos nuevos. Dos de estos eventos permiten que una subclase pueda determinar cmo utilizar la enumeracin (DepthFirst) y permite que una sublcase pueda interrumpir la iteracin (Stop). Ambos funcionan correctamente con los valores devueltos por omisin. De modo que en realidad una subclase slo necesita implementar un manejador de evento (EnumerateItem). 2 Abre la clase FileCounter y observa lo sencillo que resulta crear una clase hija encargada de contar los archivos de esa ubicacin. 3 Regresa a la clase FileEnumerator y examina la estructura recursiva del proceso correspondiente a la enumeracin de archivos. Observa cmo se realiza la enumeracin de tipo primero en profundidad enumerando recursivamente de forma inmediata cualquier carpeta que se encuentra, mientras que una enumeracin del tipo primero a lo ancho se realiza enumerando en primer lugar todos los elementos de una carpeta y posteriormente enumerando de forma recursiva los contenidos de cada una de las subcarpetas. 4 Aade un punto de parada en el mtodo Enumerate del FileEnumerator. Ejecuta el programa y elige una carpeta que contenga una pequea cantidad de archivos y una o dos subcarpetas. Traza la ejecucin. A continuacin comenta el comando: Return True En el manejador de evento DepthFirst en la clase FileCounter, ejecuta el programa y elige la misma carpeta. TrueItem Observa que cuando seleccionamos un elemento en concreto en una carpeta, utilizamos la funcin TrueItem en vez de la funcin Item correspondiente al FolderItem. La diferencia reside en el tratamiento realizado con los atajos (los atajos se denominan alias en los Macintosh): cuando Item se corresponde con un atajo este se tratar como el archivo al que apunta, mientras que TrueItem se tratar como un archivo de atajo propiamente dicho. Es importante tener en cuenta esto, dado que si seguimos los atajos hasta su fuente, sera posible quedarse enredado en una estructura de directorio en bucle, donde un atajo apuntase a una de las carpetas en las que estuviese contenido, causando por tanto que el proceso de enumeracin continuase funcionando de forma indenida.

Claramente sera mejor si siguisemos los atajos hasta sus archivos originales y de hecho es lo que haremos en un proyecto posterior. De hecho, noticaremos a la subclase mediante un evento que hemos encontrado un atajo y dejaremos que la subclase decida si lo seguimos o no. Es ms, crearemos una clase que no se quede detenida en un bucle, independientemente de lo que haga la subclase. Sin embargo, hacer esto supone una sorprendente cantidad de trabajo adicional, y tendremos que crear en las siguientes lecciones un poco de infraestructura adicional para conseguir que funcione correctamente. Conceptos utilizados en este proyecto Observa que este proyecto utiliza recursin. Esta es una forma natural de afrontar el problema, dado que los datos involucrados tienen una estructura recursiva (una carpeta es el mismo tipo de cosa que la carpeta en la que est contenida). Observa que hemos creado una clase de la que se debe crear una subclase para que pueda realizar algo de utilidad. Ten en cuenta tambin que hemos creado una clase exible que puede utilizarse de una variedad de formas. Armados con esta clase, puedes crear con rapidez una amplia variedad de utildiades de archivo. Por ejemplo, advierte la poca cantidad de cdigo adicional necesario a la hora de utilizar esta clase para crear un programa que cuente archivos y carpetas. Ejercicios adicionales Hay una amplia variedad de potenciales ejercicios que podran realizarse a partir de estos inicios. Prueba a desarrollar una utilidad de archivos til, Quiz algo que liste todos los archivos contenidos en una carpeta. Una mejora interesante podra ser la de proporcionar a la subclase la capacidad de decidir si debera de enumerarse un atajo o bien el archivo original al que apunta. Probablemente la mejor forma de hacerlo sea utilizando un evento especial para un alias: EnumerateAlias(f as FolderItem, g As FolderItem) As Boolean. El mtodo debera devolver True para indicar que el destino debera enumerarse en el caso de que fuese una carpeta, y False si no lo es. Deberas pensar sobre el problema de la estructura de directorio en bucle. No es muy difcil crear una solucin simple, pero s llevar un poco ms de trabajo conseguir algo que no se ralentice en exceso a medida que crezca la estructura del directorio observado.

Leccin 19 Estructuras de Datos Objetivo Queremos conseguir una versin del Enumerador de archivos que pueda gestionar los atajos de carpetas sin que se vea atrapado en los bucles que pueda resultar de dicha accin. El nico modo prctico de evitar este problema de bucle consiste en mantener un listado con todas las carpetas que ya se han enumerado. Antes de enumerar una carpeta, comprobaremos si ya gura en el listado. Actualmente, un ordenador moderno puede tener miles de carpetas y crear y buscar dicho listado cada vez que encontrsemos una carpeta podra llevarnos al terreno en el que nos preocupemos de la eciencia9 . Si nos limitamos a mantener este listado como cualquiera de las estructuras de datos simples que hemos visto hasta ahora (pongamos por caso un arreglo de cadenas), y buscamos dicho listado de principio a n (denominado bsqueda lineal), entonces este proceso de bsqueda ralentizara todo el proceso de enumeracin de forma signicativa a medida que aumentase el propio listado. Con todo esto en mente, esta leccin examinar otras estructuras de datos diferentes para almacenar y buscar un listado de cadenas. Observa que REALbasic incluye de serie una estructura de datos que puede hacer lo que necesitamos: el Diccionario (Dictionary). Pero aprenderemos mucho ms implementando nuestra propia solucin. El Proyecto Siguiendo con las ideas de las que hemos estado hablando, desarrollaremos una clase que llamaremos String Accumulator, y que se encarga de mantener un listado de cadenas. Dicha clase tienen un mtodo principal, sobre el que enviars una cadena. Si la cadena ya est en el listado, devuelve True; de lo contrario la cadena se aade al listado y devuelve False. Por tanto, podemos suministrar a dicho mtodo la ruta del archivo que estamos a punto de seguir, y ste nos indicar si ya lo hemos buscado anteriormente. En esta leccin examinaremos tres estructuras de datos diferentes para almacenar el listado y dos algoritmos diferentes para buscar en cada una de estas estructuras de datos. Utilizaremos un framework que nos permitir comprobar la velocidad de las estructuras de datos y de los algoritmos. Asegrate de que pasas algo de tiempo pensando sobre el modo en el que implementaras el acumulador de cadenas, utilizando para ello lo que ya hemos aprendido hasta ahora. Como hemos visto en las anteriores lecciones, no tenemos un modo prctico para comprender exactamente lo que REALbasic est haciendo de forma interna con nuestro
9

En realidad esto aun depende de las consideraciones relacionadas con tu situacin. Si creasemos una utilidad para hacer algo de forma muy ocasional, o en el caso de que procesar cada uno de los archivos fuese a llevar una cantidad de tiempo considerable, en cualquier caso, entonces no valdra mucho el esfuerzo optimizar este tipo de cosas. Sin embargo, en el caso de que estuvisemos creando algo de propsito general y que fuese reutilizable, entonces podramos optimizarlo una vez y utilizarlo una y otra vez, de modo que mereciese la pena el esfuerzo realizado para acelerarlo el mximo posible.

cdigo. Cuando se trata de cuestiones relacionadas con la eciencia, el nico modo able para determinar cul es el cdigo ms eciente para una tarea dada consiste en congurar una prueba. 1 Abre el proyecto 19_StringAccumulator La ventana principal del proyecto proporciona tres botones. El superior te permite una prueba de tiempo en la que se comparan distintas implementaciones del acumulador de cadenas. El botn inferior te permite ejecutar una prueba simple sobre un acumulador. De forma deliberada, ninguno de los botones proporciona una salida: este proyecto es simplemente un framework mnimo pero funcional que un desarrollador podra llevar a la prctica para realizar comparaciones de tiempo. Puedes limitarte a aadir puntos de parada en un mtodo para determinar su comportamiento. Por ejemplo, en el caso de que quisieras realizar pruebas de rendimiento podras incluir un punto de parada en la ltima lnea del botn superior y examinar a continuacin los contenidos del array Timings. 2 Comienza examinando la clase realmente simple StringAccumulator. 3 Examina ahora la clase ArrayStringAccumulator. Quiz esto sea lo que habas previsto cuando pensaste sobre el modo de crear la clase StringAccumulator. Bsqueda binaria Una forma de acelarar la bsqueda sobre un listado ordenador es mediante una bsqueda binaria, donde divides la lista por la mitad repetidamente. Comienzas buscando por el elemento de la mitad en el listado y restringes la bsqueda sobre la primera mita del listado, en funcin de cul sea el elemento que ests buscando. A continuacin buscas en la mitad de dicho sublistado y vuelves a dividirlo por la mitad, repitiendo este proceso una y otra vez. 1 Exmina el cdigo en el BinaryArrayStringAccumulator. 2 Examina el cdigo correspondiente al RunButton de la ventana. Comenta el cdigo encargado de aadir todo excepto el BinaryArrayStringAccumulator y el ArrayStringAccumulator. 3 Asegrate de tener un punto de parada al nal del mtodo. 4 Ejecuta el proyecto y haz clic en el botn. Al nalizar examina los valores del array Timings. Te sorprenders al comprobar la rapidez de la bsqueda binaria. Observar que una bsqueda lineal a travs de N elementos realizar de media una serie de 1/2N comparaciones, mientras que una bsqueda binaria realizar de media en torno a log2N comparaciones. Antes de que continuemos, deberas revisar la presentacin PopwerPoint: About Memory Management. Teniendo en cuenta lo que has aprendido sobre la gestin de la memdoia, deberamos tener en cuenta el uso de un Listado Enlazado creado a partir de una serie de objetos independientes. Sera imposible hacer una bsqueda binaria en este tipo de listado, pero insertar un elemento en este tipo de listado puede realizarse en una cantida de tiempo

constante, independientemente de cu sea la longitud del listado. Lo que no est claro es si este tipo de listados seran ms rpidos en comparacin con los otros listado que hemos vistado hasta ahora. 5 Examina el cdigo de la clase ListStringAccumulator2, y comenta de nuevo el cdigo del botn y ejecuta el proyecto. Ouch. La nueva clase aun tiene la mitad de la velocidad en comparacin con ArrayStringAccumulator, deja slo el array de la bsqueda binaria. A continuacin vamos a examinar algunas estructuras de datos en rbol. Estas se corresponden con tipos de estructuras de datos muy comunes y veremos la ms simple de ellas: un rbol Binario. Sobre los rboles Binarios La informacin en un rbol binario est contenida en Nodos que estn unidos por las ramas (estos sern objetos para los nodos y referencias a otros objetos como ramas): Figura 57. Ejemplo de rbol binario (Captura Figura 57) En la Figura 57, los numeros estn contenidos en los nodos y las echas representan las ramas. Cada nodo tienen una rama menor que y otra mayor que (cualquiera de ellas puede ser Nil). Para encontrar algo en un rbol binario, slo has de seguir sus ramas: Figura 58. Ubicar un valor siguiendo las ramas. (Captura Figura 58) Para insertar algo, encuentra dnde debera de estar e insrtalo en dicha posicin: Figura 59. Inserta algo en la posicin correspondiente. (Captura Figura 59) Un problema potencial es que la forma del rbol depender del orden en el que se vayan aadiendo los nodos: Figura 60. Un rbol binario no balanceado. (Captura Figura 60) Esto quiz resulte peor que una lista enlazada... El rbol en un rbol binario no balanceado. El 4 no est balanceado y funcionar tan mal o peor de lo que lo hara una lista enlazada. 6 Exmina el cdigo encargado de hacer funcionar la clase BinaryTreeAccumulator. Ejectalo mediante el botn TestOneButton y trzalo a medida que lo haces.

7 Examina la clase no recursiva BinaryTreeAccumulator2. Si no ests seguro sobre cmo funciona, trzalo desde el botn TestOneButton. 8 Reordena el mtodo RunButton de modo que podamos comparar los tiempos correspondientes a las dos clases BinaryTreeAccumulator y el BinaryArrayStringAccumulator. Comenta el manejador StackOverowException. Ejecuta la aplicacin. Wow. BinaryArrayStringAccumulator aun es varias veces ms rpido en comparacin con cualquiera de las otras opciones probadas. Otras opciones El BinaryArrayStringAccumulaotr es razonablemente rpido; en realidad varias veces ms rpido en comparacin con la lista de bsqueda lineal. Ser suciente para nuestro proyecto de enumeracin de archivos. En cualqueir caso, resulta interesante tener en cuenta cmo podramos hacer que nuestro ArrayStringAccumulator fuese ms rpido. Podramos usar un tipo de rbol ms inteligente que siempre estuviese balanceados: un rbol 2-3. Tambin existe una fuente de ineciencia en todas nuestras clases: REALbasic no sabe que nunca vamos a cambiar el tamao de nuestras cadenas, o bien que vamos a necesitar almacenar una gran cantidad de cadenas. Tomando el control sobre nuestra propia gestin de la memori a un nivel ms bajo (mediante el uso de la clase MemoryBlock) podramos lograr que todas estas clases fuesen ms rpidas. Utilizando un esquema como este, podramos llegar a la conclusin de que la versin BinaryArrayStringAccumulator deja de ser la ms rpida. Cualquier libro de texto sobre estructuras de datos debera describir el rbol 2-3; dado que constituye una de las estructuras de datos ms bsicas en ciencia de la computacin. Por la misma razn, tampoco debera de resultar difcil encontrar una descripcin del rbol 2-3 en lnea. Sin embargo, existe una razonable cantidad de cdigo involucrada en la implementacin de un rbol 2-3, de modo que se sale un poco del objetivo de este curso. Del mismo modo, las caractersticas de almacenamiento de datos incluidas en REALbasic (particularmente la clase Dictionary) hacen que sea poco probable el hecho de que vayas a necesitar implementar una estructura de datos como esa para programa en REALbasic. Otras mejoras Deberas leer la documentacin de REALbasic sobre el MemoryBlock. Un MemoryBlock es una porcin de memoria muy simple, bsicamente como si fuese un arreglo de butes. Dado que es tan simple, tambin es muy rpida. REALbasic no precisa entrar en los problemas adicionales requeridos para hacer que las cadenas resulten ms exibles. Eto signica que puedes obtener provecho de tu conocimiento sobre el hecho de que las cadenas que ests almacenando no precisan cambiar su tamao, de modo que sea ms rpido trabajar con ellas. De igual modo puedes mantener incluso un rbol binario 2-3, o para el caso nuestra lista ms simple, en un bloque de memoria de gran tamao que hara todo el proceso sustancialmente ms rpido. Existe un modo razonablemente ms simple, muy exible y eciente para acelerar prcticamente cualquier estructura de datos, denominado hashing. Emplearemos el hashing en una leccin dentro de muy poco, y veremos una mejora sustancial sobre nuestro listado con bsqueda binaria. Mientras tanto, tenemos una clase que

proporcionar un rendimiento razonable para nuestro enumerador de archivos, de modo que volvamos de nuevo a nuestro enumerador de archivos en la siguiente leccin. Ejercicios adicionales Existen una buena cantidad de ejercicios potenciales que pueden realizarse a partir de este punto. Uno interesante sera un modo bastante simple de acelerar cualquiera de las clases basadas en arrays (arreglos): aumentar su tamao de forma muy ocasional y en grandes cantidades. Esto involucrara el hecho de mantener un registro independiente sobre el tamao reservado que se est utilizando, resevando por ejemplo 1.000 o 10.000 elementos en el constructor y, pongamos por caso, duplicando el tamao del array cuando se est quedando sin espacio. Ten en cuenta que un constructor como este (al nal del mtodo SubRangeSearch, en este ejemplo): Exception E As OutOfBoundsException ReDim TheStrings(2*Ubound(TheStrings)) SubRangeSearch(S, x, y) Es perfectamente aceptable y ciertamente el modo ms sencillo de llevar a cabo el cambio de tamao del array. Apndice: Sobre la Gestin de Memoria La memoria de tu programa es bsicamente un enorme arreglo de bytes. Un bute es cualquier nmero entre 0 y 255. REALbasic se encarga de gestionar la memoria por ti. Puedes crear, destruir y cambiar el tamao de las variables y de los objetos sin preocuparte sobre los detalles. Internamente, REALbasic est registrando: Dnde se almacena cada uno de los objetos; Si un objeto aun est siendo utilizado; Cuando se puede reclamar el espacio empleado por un objeto que ya no est siendo utilizado: Dnde se encuentra el espacio utilizado y el espacio libre; y Una buena cantidad de otras cuestiones... De modo que si cambias el tamao de un arreglo de cadenas, REALbasic decide si el espacio que la variable tiene reservado resulta suciente. Si dicho espacio no resulta suciente, entonces el contenido de la variable se mueve al nuevo espacio y se reclama el antiguo espacio. Despus de crear y destruir una buena cantidad de objetos... Figura 61. Una ilustracin de memoria fragmentada. (Captura Figura 61) ...la memoria se fragmenta; o se convierte en una mezcla de porciones llenas y libres. A continuacin si pruebas a crear un objeto grande, o bien conviertes un objeto existente en otro mucho mayor, el ordenador ha de mover una buena cantidad de cosas con el objeto de hacer espacio.

De modo que si ests preocupado por la eciencia: Cambia el tamao de las cosas con poca frecuencia, en grandes porciones, en vez de hacerlo un caracter o elemento cada vez; Considera reutilizar objetos en vez de destruir un objeto y crear un nuevo objeto del mismo tipo; Considera realizar tu propia gestin de memoria para los objetos importantes empleando para ello los MemoryBlock. Resulta evidente que los desarrolladores de REALbasic procuran protegernos de la necesidad de que tengamos que llevar a cabo este tipo de tareas, y de hecho lo han conseguido al precisar que este tipo de consideraciones resulten slo importantes en situaciones de rendimiento muy crtico. Por ejemplo, si pides a REALbasic que cambie el tamao de un array un elemento cada vez, en realidad no har eso; en secreto cambiar el tamao del array utilizando tamaos mayores, manteniendo un registro sobre la cantidad de espacio reservada y la que realmente ests utilizando.

Leccin 20 Enumerador de Archivos 2 Objetivo Vamos a introducir los resultados de nuestro ltimo proyecto en el proyecto enumerador de archivos que hemos visto en las anteriores lecciones, adems de renar un poco ms el enumerador de archivos propiamente dicho. En concreto se trata de algo ms ligero en comparacin con lo visto en nuestro ltimo proyecto. Analizar el problema Comenzaremos pensando en nuestro objetivo: queremos que la clase FileEnumerator sea capaz de manejar los atajos de una forma inteligente. Debe ser capaz de hacer tanto trabajo como sea razonable, al tiempo que deja las principales decisiones en mano de la subclase (ya lo hemos hecho, por ejemplo, con la posibilidad de decidir si la enumeracin debe realizarse primero en profundidad o a lo ancho). De modo que detengmonos a pensar un poco sobre el modo en el que podemos tratar los atajos. Lo primero de lo que nos damos cuenta es que la subclase debera decidir si se debera de seguir el atajo hasta su original o no. La solucin consiste en proporcionar un Evento FollowAlias que permita tomar dicha decisin a la clase. Pero nos encontramos con otro, sutil, problema de diseo: debera el archivo de atajo enumerarse como si se tratase de un archivo normal? Dado que pasaremos el FolderItem correspondiente al alias al evento FollowAlias, decidimos no pasar ese mismo FolderItem al evento EnumerateItem. Esto es asi porque, si la subclase quiere procesar el alias junto con el resto de los archivos, puede hacerlo facilmente en el evento FollowAlias. Sin embargo, si por el contrario la clase quiere ignorar los atajos, entonces no es necesario comprobar cada uno de los FolderItem enumerados para ver si se trata de un atajo. En cuanto a los archivos apuntados por los atajos, los enumeraremos utilizando para ello el evento, EnumerateItem normal en el caso de que el evento FollowAlias devuelva True. Este diseo ser exible, pero sencillo de usar, independientemente de cul sea el comportamiento que se haya deseado para los alias. El otro problema con el que nos encontramos es cmo evitar que los atajos nos atrapen en los bucles. Ahora esto resulta sencillo de tratar: antes de que enumeremos una carpeta, comprobaremos si su ruta10 se encuentra en el listado de rutas correspondiente a las carpetas ya enumeradas. En el caso de que se encuentre en el listado, lo pasaremos por alto; de lo contrario, lo aadiremos al listado y procederemos a enumerar sus contenidos. El Proyecto 1 Abre el proyecto de enumeracin de archivos correspondiente a la Leccin 18, y examina donde se podra utilizar el acumulador de cadena para evitar los bucles provocados por los atajos. 2 Ahora abre la versin actualizada, 20_FileEnumerator2. Se ha reconstruido el proyecto para que se acomode con mayor comodidad a los nuevos objetivos. El mejor modo de separar la parte correspondiente al hallazgo de un atajo en
10

La ruta de un archivo es una cadena que especica con exactitud dnde reside. Todos los archivos y carpetas tienen una ruta nica.

un evento independiente consiste en utilizar una subclase. Sin embargo, el cdigo necesario para ello precisa de algunos cambios en la clase FileEnumerator. Del mismo modo, FileEnumerator se ha modifucado de modo que en vez de proporcionar la ruta a enumerar en un constructor lo pasamos ahora mediante la llamada a Enumerate. Esto permite que la subclase pueda reiniciar de forma recursiva el proceso de enumeracin a medida que sea preciso. Mientras que estamos haciendo cambios sobre esta clase, tambin hemos llevado la accin de encontrar una carpeta a su propio evento, proporcionando as a la subclase la oportunidad de sobreescribir la enumeracin de la carpeta. Ten en cuenta que el comportamiento por omisin consiste en no enumerar la carpeta; la subclase debe devolver True en el evento EnumerateFolder en el caso de que se quieran enumerar los contenidos de la carpeta. Por qu lo hacemos as? Porque no haba un nombre mejor para un evento con la interpretacin opuesta. SIempre es bueno elegir nombres autoexplicativos... 3 Examina la clase en la que aadimos el comportamiento correspondiente al manejo del alias. Observa cmo los mecanismos de los eventos nos permiten reinterpretar un evento: FileEnumerator enumera todo lo que encuentra mediante los eventos EnumerateFolder y EnumerateItem, sin importar si alguno de estos elementos se corresponden con alias. FileAliasEnumerator intercepta el evento EnumerateItem. y divide la enumeracin del alias en un evento diferente. 4 Ejecuta el cdigo y prubalo sobre algunas carpetas de tamao medio. La velocidad no est mal, incluso desde el depurador. 5 Por ltimo, prueba a enumerar una carpeta realmente grande (por ejemplo el raz de tu disco duro). Si tienes una buena cantidad real de carpetas anidadas, entonces puede que llegues a ver incluso un desbordamiento de la pila (aunque es poco probable). En una leccin posterior consideraremos el modo de resolver el problema correspondiente al desbordamiento de la pila. Ejercicios Adicionales Piensa sobre los tipos de utilidades que pueden desarrollarse en funcin de la capacidad de enumeracin de archivos. Antes de que lo hagamos en una leccin posterior, es probable que quieras probar a crear una versin no recurrente de este proyecto. Resultara ms claro devolver la capacidad FIleAliasEnumerator de la carpeta de nuevo a la clase principal.

Leccin 21 Hashing Objetivo Combinamos una estructura de datos simple denominada tabla hash con el listado lineal ms simple de una leccin anterior. El resultado es una estructura de datos que es mucho ms rpida en comparacin con el arreglo de bsqueda binaria. Sobre las tablas Hash El Hashing es una tcnica muy simple y utilizada ampliamente para acelerar virtualmente cualquier estructura de datos. Debe combinarse con otra estructura de datos, puesto que lo realizado es separar los elementos a almacenar y buscar en varios grupos ms pequeos; si bien aun tenemos que almacenar y buscar dichos grupos de algn modo. El motivo por el que esto resulta ms rpido es porque podemos dividir una estructura de datos mayor en varias estructuras de datos ms pequeas. La divisin es rpida, y requiere la misma cantidad de tiempo, independientemente de la cantidad de grupos que tengamos. Los grupos se generan mediante la creacin de un modo que permita generar de forma constante una clave hash a partir de cada uno de los posibles valores a almacenar. Este nmero hash debera de tener las siguientes propiedades: Debera generarse de forma razonablemente rpida; Debera encontrarse en un rango razonablemente corto (en el rango del nmero de grupos que quieras); Debera de minimizar las colisiones (valores que resulten en la misma clave). Esto signica que cada conjunto de valores aleatorios deberasn distribuirse de forma equitativa, pero tambin que un conjunto de, por ejemplo, valores muy similares deberan generar nmeros hash muy diferentes. El segundo criterio es lo sucientemente abierto a la interpretacin como para haber producido una cantidad razonable de debate en los crculos relacionados con la programacin de ordenadores. Encontrars una gran variedad de funciones de hashing en los libros de texto correspondientes a ciencias de la computacin y tambin en Internet. El algoritmo que estamos utilizando es uno encontrado en Internet razonablemente robusto. Desafortunadamente, si bien la funcin de hash propiamente dicha es razonablemente sencilla, la matemtica que se halla detrs de una funcin de hash es por lo general razonablemente compleja. Si ests interesado en los aspectos relacionados con la obtencin de una funcin hash, consulta cualquier libro de ciencias de la computacin. Uno de los mejores (sobre este y otros asuntos) es The Art of Computer Programming11. Una cosa que ayuda con prcticamente cualquier funcin de hashing es tener un mdulo primo (el nmero de grupos se denomina el mdulo en la funcin de hash). Actividades y Procedimientos 1 Abre project 21_Hashing.
11

En este caso, deberas de consultar el Volumen 3, si bien todas las series consituyen una verdadera obra de arte. Knuth, D E, The Art of Computer Programming, 2nd Ed, Addison Wesley, Reading Mass, 1997 ISBN 0-201-89685-0.

2 Examina el cdigo en el mdulo Hash, y a continuacin HashStringAccumulator y ListHashStringAccumulator. Observa lo simple que es todo ello. Asegrate de comprobar tambin cmo funcionan juntas HashStringAccumulator y ListHashStringAccumulator: en vez de que un evento pase de forma explcita de uno a otro, la subclase slo tiene que congurar el ndice de la tabla de contenidos hash. HashStringAccumulator puede emplear cualquier StringAccumulator en la tabla hash de forma polimrca; de modo que una vez que la subclase ha congurado algn tipo de StringAccumulator en cada uno de los elementos de la tabla hash, su trabajo ya est hecho. Todo esto signica que todo lo que necesita proporcionar la subclase es un constructor. Advierte tambin que tanto el HashStringAccumulator como los contenidos de su tabla hash son StringAccumulators, dado que ambos hacen lo mismo 12. El valor de la constante HashMod es uno razonable para una cantidad de datos relativamente pequea como la utilizada en este proyecto. Para facilitar el seguimiento de lo que tiene lugar, cmbialo a un valor ms pequeo (por ejemplo, 5). Ejecuta el proyecto y prueba varios valores de HashMod. Probablemente tambin quieras probar a crear otras subclases de HashStringAccumulator y medir sus tiempos. Ejercicios adicionales Una buena prueba de tu compresin sobre los aspectos relacionados con el hashing consiste en ver si puedes crear una estructura de hashing de dos niveles (tablas hash que contengan tablas hash, y que en ltimo extremo contenga alguna otra estructura como una lista). Utiliza algo de tiempo en pensar cmo podras hacerlo. Puntos adicionales si has dejado de pensar en ello, y te das cuenta de que necesitas utilizar valores HashMod distintos para dos niveles diferentes13

12

No se trata de una estrategia atpica. Esto es algo que puedes hacer como solucin a un problema: tienes una clase que llama a un mtodo sobre un nico objeto de un tipo determinado. Posteriormente decides que quieres que llame a dicho mtodo en un grupo de esos objetos. En vez de modicar la denicin de la clase, puedes escribir una clase intermedia del mismo tipo como la nica clase a la que llames ahora, y dejar que sea tu nuevo adaptador quien se encargue de pasar la llamada al resto del grupo de objetos.
13

En la prctica siempre ser mejor contar con una tabla hash grande frente al uso de mltiples niveles de tablas hash. Una tabla es ms sencilla y slo tienes que ejecutar una vez el clculo del nmero hash.

Leccin 22 Comprobacin de redundancia cclica Objetivo Esta leccin explora el extao mundo de la aritmtica binaria, mediante la implementacin de un algoritmo muy importante: la comprobacin de redunancia cclica rpida (CRC). La teora relacionada no es muy compleja, pero precisa del aprendizaje de un nuevo tipo de matemtica. Es considerablemente ms sencillo que, pongamos por caso, la aritmtica bsica que aprendiste en primaria; pero aun as resulta un poco desconcertante, de modo que si no te sientes como en casa, no te preocupes... es normal. Digamos que se trata de una leccin opcional. Vamos a llevar a cabo esta leccin porque las Comprobaciones de Redundancia Cclica (CRC) son muy importantes, pero tambin porque pensamos que se trata de una buena leccin sobre la aritmtica binaria. Existen varios cientos de sitios web y libros en los que puedes aprender aritmtica binaria bsica, de modo que hemos pensado que no sera buena idea cubrir en este espacio el mismo tipo de contenido. En vez de ello, tomaremos una leccin diseada para que puedas comprender los fundamentos sobre el sentido de todos esos unos y ceros que gobiernan el funcionamiento de tu ordenador. Adicionalmente, en el proyecto tambin se utiliza una tcnica utilizada ampliamente para la aceleracin de los clculos CRC. Aprender matemtica binaria bsica La matemtica binaria es matemtica en base 2. Funciona del mismo modo que la matemtica en base 10 a la que ests acostumbrado, pero en la que slo puedes utilizar 1 y 0; y en vez de los dgitos de los nmeros que representan las unidades, decenas, centenas, millares, etc, estos representan unos, doses, cuatros, ochos, etc. Si a lo largo de la leccin consideras que necesitas ms informacin sobre cmo funciona la matemtica binaria, prueba a realizar una bsqueda en google sobre matemtica binaria. Qu es la Comprobacin de Redundancia Cclica? Es bastante frecuente que quieras comparar dos fragmentos de informacin que se encuentran separados en el tiempo y en el espacio, en una situacin donde slo tienes una o incluso puede que ninguna de estas dos piezas. Es posible que hayas transmitido algo por la red, o que la hayas almacenado durante algn periodo de tiempo y de algn modo, y ahora quieras determinar si lo que tienes es lo mismo que el original. Un CRC es un modo de hacerlo: es una rma resumida generada a partir de la informacin, de un modo que si la informacin ha sufrido algn tipo de modicacin, entonces la rma ser diferente. Dado que el CRC es generalmente ms corto que la informacin de la que est derivado, resulta inevitable que varios bloques de datos generen el mismo CRC. Lo que queremos, no obstante, es garantizar que el CRC no ser el mismo teniendo en cuenta los patrones de errores esperados (como el cambio en el valor de terminados bits, cambio de valor en rfagas de bits, etc.)

La matemtica est un poco alejada del objetivo de esta leccin, pero no resulta muy difcil probar que el CRC que vamos a usar aqu cumple con esos tipos de criterio. Veamos por ejemplo, http://www.cs.williams.edu/~tom/courses/336/outlines/lect7_2.html como una prueba de esto. Matemtica con Polinmios Mdulo 2 En esta leccin vamoa combinar los unos y ceros nativos del ordenador en algo que son casi nmeros. Tcnicamente, son polinomios mdulo 2 14. Son prcticamente nmeros porque podemos realizar operaciones con ellos que son equivalentes a las operaciones a en las que acostumbras emplear nmeros. Un polinomio mdulo 2 es una cadena de unos y ceros, justo como cualquier nmero binario normal. Para simplicar las cosas, nos referiremos a ellos a partir de ahora como nmeros CRC. Con los nmeros CRC puedes realizar las habituales operaciones de suma, resta, multiplicacin y divisin, del mismo modo que realizas dichas operaciones sobre los nmeros binarios normales, con una excepcin: puedes ignorar el acarreo15. La nica operacin que necesitamos pra el CRC es la divisin. De hecho, el clculo de un CRC es el resto de dividir el valor por un polinomio concreto de valor jo (por lo general denominado el polinomio). Ahora, dividamos cantidades de sustraciones repetidas: 7192 ______ 72 )517843 504 ---138 72 ---664 648 ---163 144 -19

14

Consulta el Apndice 1: Polinomios Mdulo 2 en el caso de que quieras acceder a una explicacin ms detallada de lo que signica en realidad Polinomios Modulo 2. No necesitas saberlo para completar la leccin, pero no queramos dejarte sin que supieses por qu usamos dicho trmino.
15

Cuando aades 22 a 39 sobre un trozo de papel, aades el 2 al 9 y obtienes 11. Escribes 1 bajo el 2 y el 9, luego escribes un 1 ms pequeo en alguna parte bajo el 2 y el 3 en la siguiente columna. Este 1 de menor tamao es el acarreo (el tpico y me llevo una), y en la matemtica con polinomios mdulo 2 te limitas a prescindir de l. Por tanto, esta matemtica resulta ms simple y tambin muy rpida.

En este clculo, 72 es el divisor, 7192 es el resultado y 517843 es el dividendo. En este caso no hay un trmino apropiado para cada uno de los nmeros que restamos a medida que avanzamos con el algoritmo, de modo que denominaremos a dichos nmeros (como el 504 del primer paso) el substractor; y llamaremos al nmero obtenido despus de restar el substractor y bajar el siguiente nmero como el objetivo. Utilizaremos el mismo algoritmo para la divisin mdulo 2; slo necesitamos saber cmo hacer restas mdulo 2, y tambin averiguar cuantas veces restar el divisor para obtener el substractor en cada paso. Comenzaremos observando que estamos trabajando en binario, de modo que la segunda pregunta se reduce a cuando sustraer 0 o 1 veces el divisor; en otras palabras, cuando sustraer el divisor o no hacerlo. Y esto nos lleva a preguntarnos si el dividendo es inferior al objetivo o no. Comprobamos que la substacin de polinomios mdulo 2 es lo mismo que la suma sin acarreo, y por tanto es realmente lo mismo que la operacin de or exclusivo (o exclusivo). Podemos conrmarlo observando que dado que estamos ignorando el acarreo, cada posicin en la suma o en la resta es totalmente independiente de las posiciones adyacentes. De modo que echemos un vistazo a la suma o a la resta de unos y ceros cuando ignoramos los acarreos: 0+0=0 0-0=0 1 + 1 = 0 (dado que 1+1=10 en binario, pero desechamos el 1 que nos llevamos) 1-1=0 0 - 1 = 1 (dado que 1+1=0) 1-0=1 0+1=1 1+0=1 De modo que tanto si sumamos como si restamos, dos unos o dos ceros nos dan cero, mientras que un uno y un cero nos dan uno. Habrs observado que se trata del mismo resultado que obtenemos al aplicar una operacin de o exclusivo (consulta el Apndice 2: Operaciones Booleanas, para obtener ms informacin sobre las operaciones como el o exclusivo). Regresemos al asunto sobre cmo determinar si un nmero es mayor que otro o no. Dado que la suma y la resta son lo mismo, todo lo que podemos hacer para nmeros de la misma longitud es comparar su dgitos situados ms a la izquierda; si ambos tienen el mismo dgito a la izquierda del todo entonces puedes considerar cualquiera de ellos como el ms grande. Nuevamente, esto facilita el clculo del CRC: si el primer dgito de ambos, tanto el objetivo como el dividendo, son el mismo entonces restamos (hacemos un o exclusivo) del divendo; en el caso de que sean diferentes, no lo hacemos. En realidad, es incluso ms sencillo que esto: el polinomio para un CRC siempre empieza con un uno, de modo que slo tenemos que mirar al siguiente dgito del objetivo; si es un uno, entonces aplicamos un o exclusivo sobre el polinomio; si no lo es, entonces no lo hacemos. Un Ejemplo

Para calcular un CRC, encuentra el nmero de dgitos en el polinomio y aade un cero menos a los datos. De modo que en el ejemplo que estamos a punto de ver, dado que nuestro polinomio es 10011, y que tiene cinco dgitos, aadiremos cuato ceros (0000). Ahora slo queda calcular el resto cuando dividas el polinomio, ignorando los acarreos: 1100001010 _______________ 10011 ) 11010110110000 10011,,.,,.... -----,,.,,.... 10011,.,,.... 10011,.,,.... -----,.,,.... 00001.,,.... 00000.,,.... -----.,,.... 00010,,.... 00000,,.... -----,,.... 00101,.... 00000,.... -----,.... 01011.... 00000.... -----.... 10110... 10011... -----... 01010.. 00000.. -----.. 10100. 10011. -----. 01110 00000 ----1110 Echemos un vistazo a las primeras operaciones: El primer paso consiste en dividir 10011 entre 11010 (observa que slo necesitamos observar la misma cantidad de dgitos que tiene nuestro polinomio cada vez). Dado que 11010 empieza con un 1, y que nuestro polinomio siempre empieza con un 1, podemos tomar el Polinomio como menor, de modo que lo restamos. El resultado es 01001. Eliminamos el 0 de la izquierda y pasamos al siguiente dgito del dato para obtener 10011, nuestro siguiente objetivo. Ahora estamos dividiendo el polinomio entre 10011. Nuevamente, el dgito de la izquierda es un 1, de modo que volvemos a restar el polinomio. Esto nos da como resultado 00000, de modo que cuando nos movemos al siguiente dgito del dato tenemos 00001.

Ahora, el dgito de la izquierda es un 0, de modo que no restamos el polinomio. An tenemos 00001, de modo que ahora movemos el siguiente dgito del dato para obtener 00010. Lo mismo de nuevo, de modo que obtenemos 00101. Etctera. Dado que nuestro polinomio siempre empieza con un 1, el proceso resulta bastante sencillo: si la posicin situada en el extremo izquierdo empieza con un 1, hacemos un o exclusivo sobre el polinomio, de lo contrario no. Acelerndolo Echa un vistazo a las primeras lneas de nuestro ejemplo: 1100001010 _______________ 10011 ) 11010110110000 10011,,.,,.... -----,,.,,.... 10011,.,,.... 10011,.,,.... -----,.,,.... 00001.,,.... Advierte que aplicar un XOR sobre una serie de nmeros puede realizarse en cualquier oden16 . Para calcular a XOR b XOR c, podemos calcular a XOR b y aplicar un XOR sobre el resultado con c, o podemos calcular b XOR c y aplicar a continuacin un XOR del resultado con a. Esto es similar a la suma y a la multiplicacin, dado que tambin podemos realizarlas en cualquier orden. Ahora, considera lo que ocurre a medida que realizamos los XOR sobre cada par de dgitos en el dividendo: para un posible par de dgitos en el dividendo, siempre haremos un XOR con el mismo par de valores. De este modo, si observamos los dos primeros pasos del ejemplo, estarmos aplicando un XOR con: 10011, 10011 ----110101 De modo que podemos realizar los dos primeros pasos del anterior clculo haciendo un XOR con 110101. Si realizamos un clculo equivalente con los cuatro posibles valores que puede tener un par de dgitos del dividendo, entonces podremos recorrer el dividendo de dos dgitos en dos dgitos, haciendo XOR con un valor obtenido de la tabla. Este sera el aspecto que tendra dicha tabla:

16

El trmino tcnico de decirlo es: La operacin XOR es conmutativa.

Dato 00 00000 000000 000000 00000 010011 010011 10011 000000 100110 10011 010011 110101

XOR con

01

10

11

El sistema de aceleracin ms comn consiste en desarrollar ms este concepto construyendo una tabla con 256 elementos y recorrer el dato un byte cada vez. Un comentario nal: tienes que utilizar polinomios muy particulares para obtener buenos resultados. Calcular cul sera un buen polinomio requiere cierta matemtica avanzada en comparacin de la que deseamos cubrir aqu. El Institute of Electrical and Electronic Engineers (IEEE; http://www.ieee.org) supone una buena fuente en la cual buscar dicha informacin. Una bsqueda en Google sobre crc polinomios ieee proporcionar un listado de resultados con buenos polinomios que puedes utilizar sobre CRCs de diversas longitudes. El utilizado en el proyecto de ejemplo es un buen polinomio para CRCs de 32 bits y 32 bits supone una buena longitud para la mayora de los propsitos. El proyecto El proyecto incluido implementa un CRC operado mediante una tabla y desarrollado en REALbasic. El cdigo es sucientemente corto y sencillo. 1 Abre el proyecto CRC y echa un vistazo al cdigo en la Clase CRC. Empieza con el mtodo BuildTable. Crear la tabla es sencillo: slo has de realizar los clculos del CRC para todos nmeros binarios del 0 al 255, un bit cada vez. 2 Ahora echa un vistazo al constructor. Observa que creamos la tabla y denimos el valor de inicio del CRC a todos 1. 3 A continuacin, echa un vistazo al mtodo Add sobre el que has de pasar una cadena. Consiste en un bucle sobre los bytes de la cadena, aplicando un XOR sobre el valor actual del registro con la entrada de la tabla correspondiente. 4 Por ltimo, observa que la obtencin del resultado es una operacin separada del clculo del CRC (mediante el mtodo Value).

Al hacerlo de este modo, podemos suministrar los datos a travs de una serie de etapas. Podemos seguir llamando a Add con el fragmento de dato, hasta que hayamos ledo toda la informacin. Esto resulta especialmente til para, por ejemplo, el software de comunicaciones, en el que podemos estar recibiendo la informacin en una serie de fragmentos en vez de toda al mismo tiempo. Usar los CRC Recuerda lo que hacen los CRC: nos proporcionan una rma para un fragmento de datos. Los usos para dicha capacidad estn limitados slo por tu imaginacin. Un par de ejemplos: Puedes utilizar un CRC sobre un archivo para garantizar que no haya sido modicado (quiz el archivo de preferencias del programa); Puedes calcular un CRC para un documento y encriptarlo a continuacin. Si utilizas un sistema de encriptacin de clave pblica, encontes alguien podra vericar que un documento proviene de ti (dado que podra desencriptar la clave encriptada y obtener un CRC vlido para el documento). Si no sabes en qu consiste la encriptacin con clave pblica, puedes leer sobre ello en Internet. Es una forma de encriptacin realmente sorprendente y til. Ejercicios Adicionales En este punto existen una serie de ejercicios adicionales ciertamente interesantes: Amplia el ejemplo para que utilice una tabla de 65536 elementos, de modo que podamos duplicar la velocidad del clculo. Modica el ejemplo de modo que slo necesitemos calcular la tabla una vez (particularmente til en el el caso del la tabla con 65536 elementos). Probablemente est involucrada la creacin de un objeto de tabla o propiedad de Mdulo, y pasarlo a la calculadora de CRC. Sobrecarga el operador Add para que acepte otros tipos de datos: un array de strings, un nmero; un array de nmeros.

Leccin 23 Ejemplo de Calculadora RPN Objetivo Hemos terminado con todo el material difcil; a continuacin echaremos un vistazo a algunos ejemplos. Vamos a crear una calculadora simple en Notacin Inversa Polaca (RPN; Reverse Polish Notation). Si alguna vez has usado una calculadora cientca de Hewlett-Packard, entonces habrs usado RPN. Adems de consistir en una buena prctica, este proyecto te ayudar a pensar sobre cmo implementar y usar una estructura de datos de pila (stack, en ingls). Tambin introduciremos el paradigma de diseo de software Modelo-Vista-Controlador. Modelo-Vista-Controlador Gran parte de este curso ha sido diseado para ayudarte a comprender lo que hacen los objetos y las caractersticas del lenguaje REALbasic, adems de cmo combinar ambos elementos en programas sosticados. En este proyecto avancermos desde el nivel de detalle que hemos estado manejando hasta ahora, a uno ms amplio que nos permita observar el modo de estructurar todo un programa: el paradigma de Modelo-Vista-Controlador (MVC). Antes de que veamos el MVC en mayor detalle, deberamos considerar otro tema que ha surgido a lo largo de este curso: la eciencia. MVC puede resultar algo excesivo para muchos programas. Recuerda lo que hemos dicho con anterioridad: en muchas situaciones, deberas estar escribiendo programas rpidos, simples, y malos slo con el propsito de solucionar un problema lo ms rpido posible. Pero antes de disear un programa ms signicativo, el paradigma MVC parece ser una va til para estructurarlo. Si ests diseando un programa que se encuentre en un punto intermedio, entonces tambin puedes emplear una estructura a medio camino del MVC. Sobre los detalles, MVC es un concepto muy generalizado, aplicable prcticamente a cualquier tipo de programa. Este indica que tus programas deberan de encontrarse divididos en objetos que asuman tres papeles bien diferenciados: Los objetos del Modelo constituyen los datos que ha de manejar tu programa. En un programa de procesamiento de textos, esto se correspondera con el texto y el estilo, junto con otra informacin de formato adicional que indique el contenido del documento. En un juego de ordenador, esto podra corresponderse con la ubicacin del mundo del juego, as como las acciones de cada uno de los actores del juego, la puntuacin del jugador, etc. La Vista es una clase o conjunto de clases encargadas de presentar el modelo al usuario en la pantalla; y El Controlador es una clase o conjunto de clases que pueden manipular el Modelo. Mediante la separacin de cada uno de estos tres papeles obtenemos la capacidad de modicar cualquiera de ellos incidiendo mnimamente en el resto de los componentes. Por

ejemplo, aumamos que creamos un programa de textos utilizando MVC. Asumamos ahora que queremos hacer que el programa sea multiusuario y permita que dos o ms usuarios trabajen sobre el mismo documento a travs de Internet. Prcticamente el nico cambio que deberamos escribir sera sobre un nuevo conjunto de clases controlador. El modelo y la vista permaneceran prcticamente sin cambios. Un aspecto clave: una nica clase puede realizar el papel de dos o incluso las tres partes del paradigma MVC. Tal y como veremos, las interfaces nos permiten separar los papeles dentro del objeto. Esto facilitar el hecho de separar cada uno de los tres papeles en varios objetos posteriormente. La estructura de datos Pila Una pila es una estructura de datos con, como mnimo, las siguientes operaciones: Push, y que toma un solo argumento; Pop, una funcin que devuelve un nico resultado del mismo tipo utilizado por el argumento Push; y Empty, una funcin que devuelve un Booleano. Estas operaciones sobre la pila funcionan de un moodo equivalente a una pila de platos en una cafetera. Los elementos abandonan la pila en el orden opuesto a cmo se apilaron. En las situaciones en las que no puedes controlar la pila desde el lenguaje de programacin, o incluso en el caso de que puedas, es probable que quieras disponer de ms operaciones sobre dicho elemento. Algunas de las otras operaciones comunes que puedes desear son: Drop, que elimina el elemento que ocupa la parte superior de la pila; Duplicate, y que aade una copia adicional del elemento situado en la parte superior de la pila. Over, y que se encarga de poner el elemento situado el segundo por arriba en la primera posicin de la pila (parte superior); Swap, y que se encarga de intercambiar la primera y segunda posiciones correspondientes a la parte superior de la pila; Size, y que devuelve el contador de los elementos de la pila, y Clear, encargada de vaciar la pila. Notacin Polaca Inversa Ya hemos visto con anterioridad que cualquier expresin matemtica puede representarse como un rbol sintctico. Y hemos visto cmo un proceso recursivo (en el que se usa una pila) nos ayuda a recorrer dicho rbol. Combina ambas observaciones y obtendrs una Notacin Polaca Inversa (RPN). En las RPN las operaciones se escriben despus de sus operandos, en vez de entre ellos. Un operando es como un argumento en el caso de una funcin: es la informacin que debes aportar a la operacin. En la expresin 2+3 el + es la operacin, mientras que el 2 y el 3 son los operandos. Para interpretar una expresin RPN, slo tienes que leerla de izquierda a derecha; los nmeros se introducen en una pila, mientras que las operaciones cogen sus argumentos

de la pila devolviendo a dicha pila el resultado obtenido. Observa lo sencilla que resulta dicha regla de evaluacin en comparacin con las reglas involucradas en las expresiones aritmticas normales. No hay reglas de precedencia que precisen que debas avanzar o retroceder para evaluar la expresin y tampoco existe la necesidad de emplear parntesis. Una observacin rpida: hablamos de la pila como los platos en una cafetera: los primeros se encuentran en la base, mientras que los ltimos ocupan la parte superior. Pero la convencin en la industria informtica consiste en ilustrar una pila en un papel como una lista, empezando la parte inferior de la pila en la parte superior de la pgina. Esto es simplemente una cuestin de acostumbrarse a ello. Algunos ejemplos de expresiones en notacin normal y RPN: Notacin normal 2+3 (2+3)*4 2+3*4 RPN 23+ 23+4* 234*+

Recuerda, en la expresin 2+3*4, teniendo en cuenta las convenciones de la aritmtica, realizamos la multiplicacin en primer lugar, de modo que el resultado es 14. Sin embargo en la versin RPN de esta expresin existe un * antes del +, indicando por tanto el orden en el que deben realizarse los clculos. Veamos cmo evaluamos las dos ltimas expresiones. En primer lugar, 2 3 + 4*: Secuencia de evaluacin de la expresin 23 + 4 * Ahora, 2 3 4 * +: Secuencia de evaluacin de la expresin 234 Pila 2 3 4 Pila 2 3 5 5 4 20

* +

2 12 14

El Proyecto Abre el proyecto SimpleRPNCalculator. Ejectalo y realiza algunos clculos. Las clases y las Interfaces Se han agrupado los elementos del programa segn su papel en el paradigma MVC. La Clase StackDisplay y el Interface Stack Observa en primer lugar que slo tenemos una clase View: la clase StackDisplay. Pero esta clase soporta un interface, Stack, y que forma parte del Modelo. El interface Stack dene el tipo de operaciones de pila que hemos visto anteriormente. El interface StackEntry El otro interface del Modelo que se ha denido es StackEntry. Este interface ha sido creado de modo que podemos tratar la caja de entrada como parte de la pila. Si el usuario ha escrito un nmero pero no ha pulsado Enter, no trataremos la informacin introducida como el elemento superior de la pila. Los mtodos de este interface permiten que la pila pueda comprobar si hay informacin en la caja de entrada, e introducirlo en el caso de que haya algo. La pila puede ocuparse por tanto de tratar este objeto adicional como parte de s misma, de modo que las otras partes de la aplicacin no necesitan preocuparse de este aspecto. Utilizamos un interface para esto de modo que el objeto de la pila no tenga que estar conectado directamente con ningn objeto de entrada en concreto. La pila no necesita saber nada sobre cul es el objeto de entrada (de datos), slo que soporta las operaciones correspondientes a la interface de StackEntry. La clase StackOperationButton La clase StackOperationButton es una clase abstracta, encargada de aadir soporte para la interface StackOPeration al BevelButton estndar (y que estamos usando como un botn independiente, slo que tiene ms el aspecto de un botn de una calculadora en comparacin con el de un botn estndar). La interface StackOperation La interface StackOperation se encarga de denir un objeto que sabe cmo manipular la pila; y eso slo signica que puede almacenar una referencia al objeto Stack cuando se le pide. La clase NumEdit Hemos tomado la clase NumEdit de una proyecto anterior. Reutilizacin del cdigo! La clase StackEntryBox Esta aada las interfaces StackEntry y StackOperation a la clase NumEdit. Observa el modo en el que se declaran mltiples interfaces para una nica clase. CalcWindow

Manejadores de Evento de Objeto en una ventana En este proyecto hemos hecho algo que no hemos realizado anteriormente: hemos puesto sustanciales cantidades de cdigo en los manejadores de evento correspondientes a los objetos de la ventana. Slo deberas hacer esto con el cdigo que sea especco para el funcionamiento de la ventana, o del que tengas la absoluta certeza que no necesitars utilizar fuera de la ventana. En este proyecto, necesitbamos una amplia variedad de botones, cada uno de ellos con un comportamiento diferente. Hemos incluido tanto comportamiento como es razonable en una denicin de clase compartida, y el resto en el cdigo correspondiente a cada uno de los manejadores de evento para cada botn de la ventana. Observa que cada vez que aadimos cdigo al manejador de evento de un objeto en una ventana, estamos creando de hecho una nueva subclase (sin nombre) sobre la clase de dicho objeto. El manejador de evento Open en CalcWindow El Manejador de Evento Open en CalcWindow hace algo que no hemos hecho anteriormente: utiliza el operador IsA para comprobar de forma especca el tipo de cada objeto de la ventana. Deberas sopesar cada vez que te sientas inclinado a usar el opeardor IsA. Siempre deberas de preguntarte a ti mismo si el polimorsmo podra haber realizado el trabajo correctamente. En este caso, de hecho, podra haberlo hecho; cada objeto de la ventana podra soporta la interface StackOperation, y los objetos que no son objetos StackOperation del diseo actual podran haber dejado vacos los mtodos para las StackOperations. Pero esto habra signicado aadir una interface extra a la clase StackDisplay que no pertenece aqu, y eso habra confundido la autodocumentacin del diseo. Tambin habra aadido complejidad sin obtener un benecio evidente. El cdigo de inicializacin de la ventana mantiene todo este material en un nico sitio, y es realmente sencillo de comprender y de mantener. Por cierto, esta situacin, en el que tienes cierto tipo de coleccin y necesitas hacer algo sobre algn objeto determinado de la misma, es una clsica situacin de no hay respuesta correcta en la programacin orientada a objetos. Utilizando IsA para encontrar los objetos que quieres resulta con frecuencia (aunque no siempre) una buena situacin frente a dicha situacin. Ejercicios Adicionales Este es un gran proyecto para su ampliacin: Aade ms botones, para ms funciones cientcas o de negocios. Aade atajos de teclado. En vez de requerir su conguracin en una ubicacin centralizada, las teclas en la ventana deberan de permitir el registro de sus propios atajos de teclado Esto nos premitira retener una importante caracterstica del programa: puede aadirse una nueva tecla, sin aadir cdigo en ninguna parte salvo en la propia tecla. AsyncKeyeDown (bscalo en la documentacin) es un modo de interceptar la

pulsacin de teclas. Una cuestin interesante sobre el diseo es cunto pondras de dicha caracterstica en una denicin de clase. Otro aspecto interesante consiste en saber cmo gestionar dos o ms botones que solicitan el mismo atajo de teclado; no existe un nico modo obvio de resolverlo. Aadir modicadores de teclado. Debera de poder obtener Sin-1 manteniendo pulsada la tecla Mayscula mvil y haciendo clic sobre el botn Sin. Del mismo modo, debera de poder escibir el cdigo especco de cada operacin alternativa en los botones propiamente dichos. Una buena prueba de tu comprensin sobre el paradigma MVC consistira en separar la pila de la visualizacin. Es equivalente a decir que la pila debera de ser una propiedad independiente de la ventana, separada de la vista. Exsiten mltiples formas de manejar la interfaz de usuario y su vista en esta situacin: la pila podra enviar simplemente una llamada Changed a la vista, y la vista podra pedir entonces los contenidos a la pila; o la pila podra noticar a la vista de cada evento que tuviese lugar sobre ella. Una opcin interesante consiste en hacer que los botones notiquen a la vista cuando hayan nalizado una operacin, as como dejar que la pila notique a la vista en dicho momento (esto sera lo ms eciente, pero tambin sera lo ms difcil de escribir; nuestras discusiones sobre aspectos relacionados con la eciencia te diran que el cdigo eciente no es necesario en este caso, pero este resultara un ejercicio de programacin interesante).

Leccin 24 Calculadora RPN Programable Objetivo Haremos que la calculadora de la ltima leccin sea programable con RBScript. Este es un ejercicio interesante, dado que la capacidad de RBScript para comunicarse con otras partes del mismo programa son inicialmente un tanto limitadas17. Acerca de RBScript RBScript es una clase que puede ejecutar programas REALbasic. Dichos programas se cargan en un objeto RBScript como texto, siendo compilados a continuacin para su ejecucin. Esto signica que puedes hacer que tu programa sea modicable por el usuario nal. Ten en cuenta que actualmente est disponible para RBScript un subconjunto de todo el lenguaje REALbasic. Consulta la Referencia del Lenguaje para obtener ms detalles. En este punto deberas leer toda la informacin disponible sobre RBScript en la Referencia del Lenguaje. El reto El reto en usar RBScript es que slo ofrece un modo muy simple de comunicarse con el resto del programa. El cdigo que se est ejecutando en un programa RBScript tiene acceso a prcticamente todo el lenguaje de programacin REALbasic, pero no a cualquiera de los objetos incorporados en REALbasic. Slo hay dos comandos que pueda utilizar un programa de RBScript para comunicarse con el resto del programa: La funcin Input y que toma un nico argumento de cadena llamando a continuacin al manejador de evento Input del objeto RBScript, y que recibe la misma cadena como argumento. El manejador de evento puede devolver una cadena, y que constituye el resultado de la funcin en RBScript. El comando Print y que toma un nico argumento de cadena y llama al manejador de evento Print del objeto RBScript, encargado de recibir la cadena como argumento. RBScript no puede llamar a ninguna parte del programa sobre el que est ejecutndose, o bien utilizar algn otro modo de comunicarse con dicho programa ms all que los dos comandos indicados. El reto consiste en que queremos proporcionar la capacidad de aadir cdigo RBScript a un botn y ampliar las capacidades de RBScript de modo que soporte algunos comandos adicionales para comunicarse con la pila de la calculadora. Implementaremos dos funciones (Pop y Size) y mtodos de tamao (Clear, Drop, Dup, Over, Swap y Push).

17

Esta leccin fue escrita cuando RBScript estaba en sus primeras encarnaciones. RBScript es ahora mucho ms exible y potente, y tambin mucho ms sencillo de usar en tus proyectos. Se ha mantenido esta leccin inalterada porque es un buen proyecto para ilustrar varias tcnicas de programacin. Del mismo modo, la mayora de las tcnicas utilizadas aqu aun resultan tiles, con ciertas variaciones, incluso cuando se est usando la ltima versin de RBScript. Una versin del proyecto que usa una de las nuevas caractersticas de RBScript se incluye en RBScript Calculator (Contexto).

En este punto deberas detenerte y pensar sobre cmo podras permitir que el usuario nal escriba un script como este: Dup Push Pop * Pop cuando RBScript no proporciona dichos comandos de pila. Consejo: tendrs que aadir cdigo adicional al RBScript proporcionado por el usuario, y en el que se incluya la implementacin para todos los comandos de la pila. Dichos comandos necesitarn comunicarse con la pila mediante los comandos Print e Input. El Proyecto Abre el proyecto RBScriptCalculator. Lo que haremos ser denir un Protocolo para que el cdigo RBScript pueda comunicarse con el resto del programa. Un protocolo es un conjunto de reglas que todo acuerdan en cumplir. En ete caso deniremos un conjunto de mensajes que pueden enviarse mediante los comandos Input y Print en RBScript, as como los los eventos asociados en el objeto RBScript, y que implementar los comandos de manipulacin de pila que necesitamos. A continuacin aadiremos cdigo adicional al RBScript proporcionado por el usuario, y que implementa los mtodos encargados de manejar el protocolo para cada accin. Para el usuario nal aparecer como si dichos mtodos formasen parte de RBScript. 1 Abre el editor de cdigo correspondiente a la clase StackScript. 2 Examina los manejadores de evento Input y Print. El protocolo es bastante sencillo. Por ejemplo, si recibimos la cadena Pop en el RBScript, extraeremos el valor situado en la parte superior de la pila y lo devolveremos. El comando ms completo es Push y que necesita soportar la recepcin de un argumento desde el RBScript. Lo que hacemos es separar el valor del comando mediante un espacio. 3 Examina ahora el cdigo llamado desde el constructor en esta clase. Para simplicar la adicin de mtodos adicionales al RBScript crearemos una cadena mediante algunos mtodos auxiliares. Comenzamos advirtiendo que slo hay tres tipos de funciones o mtodos que precisamos aadir a la cadena que estamos almacenando en TheScriptHeader, y que ser incorporada al cdigo RBScript del usuario: Mtodos sin argumentos: Mtodos con un argumento; y Funciones sin argumentos Observamos que todos ellos hacen lo mismo: pasan su nombre mediante los comandos Input o Print. En el caso de que haya un argumento, este se pasa mediante el mismo comando, separado del nombre con un espacio. De modo que creamos tres mtodos auxiliares para gener declaraciones de mtodo o funcin, teniendo en cuenta el nombre del mtodo o de la funcin, y entonces llamamos al mtodo auxiliar correspondiente para cada mtodo o funcin que tengamos que aadir al TheScriptHeader. Observar que tenemos una AddFunction1 que no usamos nunca; slo

est ah por cuestiones de completitud, en el caso de que queramos ampliar este proyecto en algn momento dado. Aparte del material indicado, se encuentran mtodos getter y setter para el script propiamente dicho, un mtodo SetStack (de modo que esta clase pueda sera una StackOperation) y eso eso es todo. 4 Revisa RBScriptButton y ButtonEditWindow para ver cmo funciona todo esto. 5 Ejecuta el proyecto y haz Alt + clic (Opcin + clic en el Macintosh) sobre uno de los botones vacios y aade un script en l. Por ejemplo: Dup Push Pop * Pop Ejercicios adicionales Este es un gran proyecto para su ampliacin: No existe ninguna gestin de errores, lo que hace que resulte muy sencillo conseguir que el programa provoca una excepcin no gestionada (unhandled exception). Aade la gestin de errores suciente para que no haya modo de que el usuario pueda provocar una excepcin no gestionada. Probablemente debieras ignorar algunos errores, y mostrar el comando ms til que puedas sobre el resto. Ten en cuenta que el objeto RBScript tiene una propiedad para indicarte qu lnea se est ejecutando. Sera buena idea indicar al usuario qu lnea de RBScript est causando un error. Aade comandos adicionales que puedan ser empleados por el usuario. Por ejemplo, seran tiles comandos para leer y escribir datos desde archivos; y Un ejercicio ms ambicioso sera el de que la calculadora guardase los scripts en sus botones cuando se salga de la aplicacin, volviendo a cargarlos la prxima vez que se ejecute. La funcin PreferencesFolder es muy til para esto...

Leccin 25 Grcos I Objetivo Vamos a trabajar con material divertido relacionado con los sprites. En consonancia con las tcnicas de programacin que hemos visto, vamos a comenzar con una pequea pieza y probarla. Esta pieza es una imagen que puede apuntar en diferentes direcciones. Este tambin supone un ejemplo excelente de por qu deberas de haber prestado ms atencin durante las clases de trigonometra en el colegio... Vamos a crear una jerarqua de clase para genera y mostrar un grco que pueda apuntar en diferentes direcciones. Dado que vamos a utilizarla posteriormente, queremos ser capaces de pasar las coordenadas x e y, relativas al centro del objeto, y permitirle que apunte hacia dichas coordenadas. Esto implica usar algo de trigonometra. Pero no te asustes, te explicaremos la trigonometra necesaria a medida que la usemos. Pre-lectura Deberas leer sobre los objetos Canvas y Graphics en la Gua del Usuario antes de continuar. El Proyecto 1 Abre el proyecto incluidos, DrawChevron, ejectalo y observa lo que hace. 2 Examina el cdigo que reside en la clase DirectedChevron, comenzando en la parte superior de la jerarqua: DirectedPicture es una clase abstracta que permite su reutilizacin; BufferedPicture es un tipo de clase abstracta que proporciona un framework de una solucin bsica para este problema: en vez de generar una imagen que apunte con precisin hacia el punto deseado, tenemos una cantidad de imgenes pregeneradas, (por lo general 8 o 16, identicado por loa propiedad NumPics) y mostramos aquella que apunte lo ms cerca de las coordenadas en las que estemos interesados. DirectedChevron nos da algunas imgenes reales que pueda mostrar BufferedPicture. Pxeles En la pantalla de ordenador una imagen se reduce en ltima instancia a una rejilla de pequeos cuadrados o celdas coloreadas. Cada una de estas celdas se denomina pixel (abreviatura de picture element elemento de imagen). Coordenadas Tradicionalmente, una posicin en una imagen bidimensional de un ordenador se mide desde la parte superior izquierda de la imagen. Un punto se describe mediante dos nmeros, y que representan la distancia hacia la derecha y hacia abajo de este punto. Dichas distancias son denominadas generalmente como las coordenadas x e y, respectivamente. Como abreviatura, en ocasiones escribiremos la posicin de un punto (x,y). De modo que la posicin inicial superior izquierda sera (0,0) y un punto que se encuentre 100 puntos hacia la derecha y 50 unidades hacia abajo se escribira como (100,50).

La trigonometra Trigonometra signica el estudio de los tringulos. Las funciones trigonomtricas relacionan los ngulos de un tringulo equiltero con la longitud de sus lados. Algo que debes saber sobre todas estas funciones en REALbasic: los ngulos se miden en radianes, por varias razones matemticas en las que no entrareremos por ahora. Existen 2 * Pi radianes en un crculo completo. Esto slo signica que donde te veas tentado de utilizar 360 (dado que piensas en grados), debes escribir 2 * Pi, y que donde te veas tentado de usar 180 escribas Pi. (Tambin querrs denir una constante Pi, tal y como tenemos en este proyecto). DirectedChevron.GenerateFrame El papel de DirectedChevron es el de proporcionar las sucientes imgenes para crear un giro de un cuarto. La superclase se encargar de crear la simetra de dichas imgenes para crear las sucientes imgenes que completen un giro total. Situaremos los puntos del chevron en torno a un crculo que quepa justo dentro de ThePicture. Comenzaremos calculando el radio de dicho crculo. Este es de la mitad del ancho de ThePicture: Figura 62. El Chevron dentro de ThePicture. (captura Figura 62) A continuacin, calculamos cuantos radianes rotaremos cada imagen en comparacin con la ltima: AngleInc = 2 * Pi * (n-1)/NumPics // cunto vamos a rotar Figura 63. AngleInc radianes incrementados para cada imagen. (Captura Figura 63) AncleInc Radianes en torno al crculo A continuacin, calculamos donde residir cada punto en el crculo. Cada punto estar representado por su distancia x (horizontal) e y (vertical) desde la esquina superior izquierda del ThePicture. La parte frontal del chevron est en AngleInc radiantes en torno a las 12 en punto. Necesitamos un modo de convertir un ngulo en sus componentes x e y. Trigonometra bsica Ahora tenemos que hallar dnde se encontrarn las tres puntas del chevron. Para ello necesitamos convertir un ngulo y una distancia en coordenadas x e y. Asumamos por el momento que el centro de nuestro chevron est en (0,0). Queremos un punto rotado p radianes, y r pxeles desde (0,0). Esto nos permite dibujar un tringulo: Figura 64. La tarea consiste en hallar a y b en este tringulo.

(Captura Figura 64) Unidades a Unidades b Unidades r p radianes Nuestro punto de partida es el punto inferior del tringulo, y el punto que queremos hallar es el punto situado a la derecha en el tringulo. Podemos dibujar dicho punto puesto que yendo r pxeles a un ngulo determinado de p radianes desde la vertical es lo mismo que subir b pxeles y moverse a continuacin a pxeles a la derecha. Observa que ir recto hacia arriba y despus recto hacia la derecha signica que ambos movimientos se producen en ngulo recto. Dos funciones trigonomtricas, Sin y Cos nos permiten hallar a y b: El Sin de p nos indica el valor de a/r. Dado que conocemos el valor de r, y queremos saber el de p, entonces resulta que a es igual a r * Sin(p). De igual modo, el Cos de p es b/r, de modo que b es igual a r * Cos(p). En general estas funciones pueden utilizarse en cualquier tringulo con un ngulo recto en la arista. La cara opuesta del ngulo recto se denomina hipotenusa. El Sin (seno) de uno de los ngulos que no se corresponde con un ngulo recto es el ratio de la cara opuesta de dicho ngulo con la hipotenusa; el Cos (coseno) del ngulo es el ratio de la cara adyacente con la hipotenusa. Tambin se encuentra la funcin Tan, y que se corresponde con el ratio de la cada opuesta con respecto a la cada adyacente. Puedes recordar todo esto con el acrnimo (en ingls) SOCHAHTOA (Sin: Opuesto/ Hipotenusa; Cos: Adyacente/Hipotenusa; Tan: Opuesto/Adyacente). Ahora queremos centrarlo no en (0,0) sino en el medio de la imagen en la posicin (r,r). De modo que sumaremos r a cada valor x e y. Tambin denimos una constante SideAngle, y que indica la distancia desde la parte superior del chevron hasta su cara opuesta en la que situamos los puntos posteriores del chevron. Esto nos proporciona el siguiente cdigo para dibujar el chevron: Sub GenerateFrame(n As Integer, g As Graphics) //Genera un chevron apuntanto al punto n en un total de UBoundPics + 1 //Pre: El ancho y alto de la imagen son idnticos //0<=n<=UBoundPics //UBoundPics >= 6, UBoundPics es par //Post: p contiene el chevron Dim r As Integer Dim AngleInc As Double Dim Points(8) As Integer Const PI=3.14159265358979323846264338327950 Const SideAngle = 0.8 //Proporcin de media vuelta sobre la parte posterior del chevron r = ThePicture.width/2

AngleInc = 2*Pi*(n-1)/NumPics //How far around we are to rotate //Punto de chevron Points(1) = r + r * sin(AngleInc) Points(2) = r + r * cos(AngleInc) //Cara lateral Points(3) = r + r * sin(Pi*SideAngle + AngleInc) Points(4) = r + r * cos(Pi*SideAngle + AngleInc) //Centro Points(5) = r Points(6) = r //Cara izquierda Points(7) = r + r * Sin(Pi*(-SideAngle) + AngleInc) Points(8) = r + r * Cos(Pi*(-SideAngle) + AngleInc) //Dibjalo g.ForeColor = DarkBevelColor g.ClearRect 0, 0 ,g.Width,g.Width g.FillPolygon(Points) Como siempre, deberas buscar cualquiera de los comando de REALbasic con los que no ests familiarizado. Sin embargo, y resumiendo, FillPolygon toma un array de enteros, trata cada par de nmeros como un punto y dibuja un polgono (la gura) entre dichos puntos, rellenndolo con el color que est denido en ForeColor. Qu imagen apunta aqu? El otro mtodo para el que necesitamos la trigonometra es el encargado de seleccionar la imgenes que debe dibujar para que apunte a una posicin concreta. Lo que necesitamos para esto es la funcin inversa de Tan mencionada anteriormente: en esta ocasin, tenemos la posicin y queremos hallar el ngulo. La parte de la ubicacin dividida por la parte x de la coordenada se corresponde con la Tan (tangente) del ngulo, tal y como se ha mencionado anteriormente. Existe una funcin Atan que calcula el ngulo a partir de este ratio pero, de hecho, REALbasic cuenta con una funcin de uso ms sencillo: Atan2 toma un valor x e y, y devuelve el ngulo desde (0,0) para dicho punto. De modo que slo tenemos que restar r de todo para regresar a (0,0) y usar Atan2. A continuacin slo hemos de redondear al ngulo ms cercano al que apuntan nuestras imgenes (recuerdas que AngleInc = 2 * Pi * (n-1) / NimPics) en GenerateFrame? Slo hemos de averigar cuantos de hay en nuestro ngulo). Esto nos proporciona el siguiente mtodo: Sub FaceToward(X As Integer, Y As Integer) Dim NextPic As Integer Const PI=3.14159265358979323846264338327950 NextPic = ((Round(atan2(X, Y)*NumPics/(2*Pi)+ NumPics) mod NumPics)) + 1 If NextPic <> CurrentPic Then CurrentPic = NextPic ThePicture.DrawPicture ThePics(CurrentPic), 0, 0 End If Ahora deberas echar un vistazo al proyecto y ejecutarlo, e indagar en l hasta que hayas averiguado como funciona.

Ejercicios Adicionales Existen miltples posibilidades de ampliar este proyecto, y deberas intentar poner en prctica tus propias ideas. Algunas interesantes podran ser: Crea la clsica aplicacin de par de ojos que miran al cursor, con crculos para las pupilas. Como bonicacin extra podras ampliar la aplicacin para que siga al apuntador dentro incluso de los ojos propiamente dichos (lo que signica que si el puntero se encuentra dentro de uno de los ojos la pupila estar centrada bajo el puntero). Dibuja una forma ms compleja (por ejemplo un tanque o un robot) en vez de una punta de echa, o bien Crea una clase que pueda iniciar a partir de dos imgenes bitmap (una que apunte hacia arriba, y otra en 45 grados), generando a continuacin las 8 imgenes restantes como fruto de rotar cada una de las dos imgenes originales en tres ngulos rectos.

Leccin 26 Comunicaciones Objetivo Desarrollaremos una aplicacin sencilla aunque til para demostrar el uso de los puertos TCP. La aplicacin enva un mensaje de texto a otro ordenador que est ejecutando la misma aplicacin. TCP/IP Del mismo modo que hemos visto los protocolos en otras situaciones, existen diferentes protocolos para que los ordenadores puedan comunicarse en una red. El protocolo que usaremos es el TCP/IP. Este es el principal protocolo de Internet. Al igual que con la calculadora, la implementacin subyacente del protocolo se encarga de ocultar la complejidad para el software que lo utilice. Para enviar informacin a un ordenador a travs de Internet18, debes saber dos cosas: La Direccin IP correspondiente al ordenador sobre el que se est ejecutando el programa, y El Nmero de Puerto en el que est escuchando el ordenador con el que ests intentando comunicarte. Ya has visto una Direccin IP anteriormente. Dichas direcciones estn formadas por cuatro nmeros entre 0 y 255 con puntos en entre ellos (como esta: 210.18.155.12). Contiene toda la informacin necesaria para localizar un ordenador en Internet. Un nmero de puerto es un entero entre 0 y 65535 19. Es parecido al buzn de una direccin convencional, y es as porque las conexiones a un ordenador emplean differentes nmeros de puerto de modo que puedes tener mltiples programas ejecutndose en un mismo ordenador y comunicndose con varios servidores en Internet, todos ellos al mismo tiempo. Cada paquete de informacin enviado entre dos ordenadores contiene una especicacin para el nmero de puerto en el que debe recibirse. Pero, cmo hacen los dos programas que se estn comunicando entre s para saber qu puertos han de utilizar? Existen tres posibles modos: Existen ciertos estndares aceptados y que se utilizan para determinados servicios. Por ejemplo, los servidores Web utilizan por lo general el puerto 80. De modo que cuando escribes www.realbasic.com en tu navegador web dicha direccin se traduce en una direccin IP20, enviando a continuacin un mensaje Hypertext Transport Protocol al puerto 80 en dicha direccin.
18

Usando el protocolo para las comunicacines en internet comunmente ms utilizado, TCP (Transmision Control Protocol).
19

O puede ser tambin 65537. Despus de varias horas buscando en Internet el escritor no ha podido asegurarse por completo.
20

Utilizando para ello otro servicio estndar sobre dicho nmero de puerto, denominado Domain Name Service. Es probable que hayas tenido que introducir direcciones de servidor DNS al congurar la conexin a Internet, y que indican qu ordenadores se encargan de realizar dicha traduccin de direcciones por ti.

Cuando un programa recibe una conexin con otro equipo suele solicitar al sistema opertivo un nmero de puerto aleatorio que aun no se haya utilizado, y pide al programa del otro extremo que responda en dicho nmero de puerto. Las direcciones de Internet (denominadas tcnicamente Universal Resource Locator o URL; Localizador de Recursos Universal) puede especicar el nmero de puerto despus del nombre del DNS o la direccin IP del servidor (separado de la direccin con dos puntos). Sera posible para REAL Software ejecutar un segundo programa servidor en el mismo ordenador utilziado para el servidor por omisin, y enlazar con l desde el puerto por omisin 80 utilizando una direccin normal; algo as http:// www.realsoftware.com:8080. La informacin enviada a travs de Internet est dividia en pequeos paquetes y pueden recibirse desordenados, o bien requerir la retransmisin de alguno de estos paquetes debido a algn error, pero todo esto es lo que sucede en una capa inferior proporcionada por TCP21 . El servicio TCP garantiza que el mensaje llegar intacto y que las partes que lo componen llegarn ordenados. Sin embargo, la informacin no tien por qu llegar necesariamente al mismo tiempo. Necesitamos tener esto presente cuando escribamos software de red. Con esto en mente, echemos un vistazo al proyecto que vamos a crear: ste enva un mensaje de texto al mismo programa que funciona en otro ordenador. Este ser un programa realmente til! El proyecto 1 Detente y piensa por un momento cmo sera un protocolo adecuado 22 para este proyecto. El nico problema real a cubrir consiste en cmo el programa receptor puede saber que ha llegado el mensaje completo. 2 Examina el cdigo del proyecto includo: MessageSender. Deberas leer en la referencia del lenguaje sobre el objeto TCPSocket. Advierte que todo lo que debemos de hacer es: creamos un socket receptor y le indicamos que escuche (Listen). Y si queremos enviar un mensaje, pedimos al socket de envo que enve. 3 Examina durante unos minutos el RFC 821 incluido, en el que se describe uno de los protocolos ms importantes de Internet: el SMTP. Se denomina Request for Comment porque as es como empiezan estos estndares: alguien publica una idea y pide a la gente que la comente; est publicado por la Internet

21

Un servicio de comunicaciones Internet est compuesto por varias capas. La capa TCP es la que proporciona el envo able de paquetes en orden utilizando para elo una capa inferior denominada UDP (Universal Datagram Protocol) en la que no se proporciona ninguna de estas garantas. Esto es importante para algunos propsitos, la velocidad es ms importante que la correccin (transmitiendo audio o vdeo, o reproduciendo un juego en tiempo real, por ejemplo), de modo que algunos programas necesitarn usar UDP, dado que resulta ms rpido.
22

Para asegurarte que toda esta charla sobre los protocolos es clara en un punto: es comn construir protocolos sobre otros protocolos. Un nivel inferior en los protocolos de comunicaciones en Internet slo se encargan de enviar los paquetes a donde deben ir. Otro protocolo se asienta encima de este para corregir los errores de transmisin producidos en el nivel inferior, y para unir mensajes largos a partir de los paquetes del nivel inferior, reunindolos en orden (esto nos lleva al TCP). Utilizaremos este nivel para implementar un protocolo de alto nivel inventado por nosotros para el envo de mensajes.

Engineering Taskforce (IETF), quien dene la mayora de los estndares (en su mayor parte protocolos) en los que est basado el funcionamiento de Internet. Es muy importante que los protocolos para enviar y recibir email y pginas web, y la mayora de los tipos de informacin transportados por Internet, estn disponibles para cualquiera que quiera comprenderlos e implementarlos. el IETF crea todos estos RFC deniendo cmo funcionan dichos servicios estndar y hace que estn disponibles de forma gratuita. Si quieres escribir un servidor web, un navegador web, un servidor de correo, o un programa que funcione con cualquiera del resto de estndares de Internet, eres libre de hacerlo. 4 Exmina la seccin de Puerto en la Referencia del Lenguaje. 5 Cntrate en los numerosos posibles errores que pueden ocurrir cuando se comunican en red dos ordenadores independientes. No hemos intentado gestionar este tipo de errores para mantener el ejemplo lo ms simple posible. La a mayora del trabajo en la implementacin de programas que se comunican por Internet consiste por lo general en gestionar todos estos errores. Ejercicios adicionales El proyecto puede ampliarse de varias formas: Gestiona el envo de texto con estilo (dene la propiedad Styled del TextField a True, y enva tanto el texto como la propiedad correspondiente a TextStyleData); Permite arrastrar y soltar cosas (archivos, recortes) sobre la ventana y tambin desde la ventana del otro ordenador. Cualquiera de estas ampliaciones en el proyecto requerirn, por supuesto, que amples el protocolo.

Leccin 27 SImulacin y Animacin Objetivo Vamos a llevar a cabo un ejercicio razonablemente signicativo de simulacin y animacin. Produciremos un SpriteSurface con una coleccin de las echas creadas en una leccin anterior, y las pondremos apuntando en la direccin del cursor. A continuacin veremos algunas de las ventajas de la orientacin de objetos cuando tratemos lo sencillo que resulta animar los sprites. Ten en cuenta que nuevamente habr algo de trigonometra relacionada con este proyecto. Lectura previa Antes de proseguir deberas leer sobre las clases correspondientes a SpriteSurface y Sprite. Simulacin de fsica En un juego es bastante habitual disear una simulacin fsica. Por lo general no llegarn a ser totalmente realistas, pero haremos algo que se asemeje a lo que podra ser el comportamiento de los objetos en el mundo real. En este caso, tendremos un grupo de objetos con el mismo comportamiento. En particular estos objetos tendrn: Momentum, lo que signica que tendrn una direccin y velocidad de movimiento, y que requerirn la aplicacin de una fuerza o fuerza para cambiar dicha direccin ny velocidad; y Empuje, que es la fuerza ejercida en la direccin a la que estn apuntando. La combinacin de ambas produce objetos cuyo comportamiento ser similar al de los cohetes pero desplazndose sobre hielo. Otro modo de decirlo es que estamos simuilando una situacin sin friccin y sin gravedad. Tendremos los objetos apuntando en todo momento hacia el apuntador del ratn. Puedes imaginar su aspecto? Las matemticas Necesitamos registrar las posiciones y momentum de los objetos, y aplicar empuje sobre ellos. La mayora de la matemtica relacionada hace uso de los vectores. Un vector es, a grandes rasgos, una echa: es una direccin y una distancia23 o (de forma equivalente) una distancia x e y.
23

Se suele utilizar el trmino magnitud en vez de distancia dado que un vector puede representar no slo una direccin y distancia sino tambin otras cosas que tenga direccin y cantidad; como por ejemplo una direccin y una cantidad de empuje.

Tambin proporcionamos otras tres operaciones sobre los vectores (veremos cun tiles son a medida que exploremos el proyecto): MultiplyBy Proporcionaremos una operacin para multiplicar un vector por un Double. Esto multiplica la magnitud por el Double (nmero de coma otante). Puesto que vamos a almacenar el vector como una cantidad de x e y, tenemos que escalar ambos, utilizando para ello una trigonometra muy parecida a los clculos realizados en la leccin de Grcos I. Normalized Esta funcin devuelve un nuevo vector con la misma direccin que el vector sobre la que se aplique, pero con una Magnitud de 1. Add y Operator_Add Para comprender la suma de dos vectores, imagnalos como echas y pon la segunda echa al nal de la primera24 : Figura 65. c = a + b. (captura Figura 65) Para calcular la suma de dos vectores podemos aadir simplemente los componentes horizontales de los dos vectores para obtener el componente horizontal del resultado, y los componentes verticales de los vectores para obtener el componente vertical del resultado: Figura 66. Para sumar vectores, suma por separado los componentes vertical y horizontal. (captura Figura 66) El primer proyecto 1 Abre el primero de los proyectos incluidos, SpriteFlock. 2 Examina el cdigo en la clase Vector; asegrate de que puedes ver cmo se implementa las operaciones descritas arriba. Advierte que la mayora de las operaciones modican el vector propiamente dicho, pero que la funcin Add devuelve un nuevo vector. 3 Examina el cdigo en la clase MomentumSprite Esta utiliza principios de animacin simples, moviendo el sprite segn su velocidad actual entre los diferentes fotogramas. No queremos arreglar la velocidad, de modo que la velocidad de los sprites variar en funcin de la rapidez del ordenador sobre el que se est ejecutando el programa.

24

La funcin Operator_Add nos permite denir nuestro propio operador + para esta clase. En otras palabras, nos permite halla la suma de dos vectores v1 y v2 escribiendo v1 + v2. Ten en cuenta que no hemos utilizado hasta ahora esta capacidad en ninguno de nuestros proyectos.

Ten en cuenta que si bien MomentumSprite es un sprite, y por tanto tiene propiedades X e Y enteras, necesitamos mantener las coordenadas del sprite como valores de tipo Double, para evitar errores de redondeo (lo que provocara que el sprite saltase en velocidades bajas, por ejemplo). Realizamos todos los clculos sobre la posicin utilizando los valores dobles y redondeando el resultao hacia el entero ms cercano con el objeto de obtener las propiedades X e Y de cada fotograma. Esto tambin signica que creamos una operacin MoveTo, de modo que cuando movemos el sprite hacia alguna posicin recordemos ajustar tanto la X e Y y ExactX y ExactY a la nueva posicin. Este es un buen ejemplo de por qu ajustar directamente las propiedades es menos exible en comparacin con el uso de mtodos get y set. A continuacin, observa que el momentum del sprite se mantiene como un vector, y que tenemos una operacin Apply, para aadir aceleracin al momentum actual. Para cada fotograma averiguaremos la direccin en funcin de la posicin del ratn, y aplicaremos un vector en dicha direccin para que el vector represente el momentum. El ltimo mtodo es Incrment y que se encarga de hallar la nueva posicin del sprite. Nuevamente, estamos sumando dos vectores (la posicin actual es como un vector). No utilizamos un vector para esto porque necesitamos componentes X e Y independientes en este punto. De modo que la posicin es un vector, la velocidad es un vector y la aceleracin es un vector. Sumamos la aceleracin a la velocidad y la velocidad a la posicin25 . 4 Echa un rpido vistazo por el resto del programa. Comentarios adicionales Hemos identicado las dos constantes importantes (la cantidad de sprites y el valor de su empuje) en constantes cuyos valores podamos modicar con facilidad o bien convertirlos en variables globales. Casi siempre suele resultar una mala prctica incluir directamente una constante en el cdigo. Esto no signica que en algunos casos no sea lo correcto, pero s signica que siempre deberas de pensar sobre ello antes de introducir un valor constante (nmero o cadena) en tu cdigo. Un ejemplo de un valor que est bien incluir como cdigo es PI, dado que es bastante improbable que camibe... Un problema del orden en el que se llama a los eventos en la ventana implica que no podamos inicializar todo en el evento Open de la ventana: en ese momento la ventana no est maximizada, de modo que no sabemos dnde hemos de poner los sprites. Existen varias formas de solucionarlo; en este caso hemos utilizado un mtodo simple pero prctico de poner todo en marcha un segundo despus de que se haya ejecutado la aplicacin, utilizando para ello un temporizador. De ah la existencia de InitSpriteSurface; y Ten en cuenta que de de algn modo hemos separado en esta simulacin la visualizacin del sprite (no lo hemos separado de forma agresiva, tal y como hemos comentado anteriormente, porque queremos mantener el cdigo simple). Esto ser importante para nuestro siguiente proyecto, donde veremos lo sencillo que resulta animar los sprites como resultado.

25

Si tienes conocimientos bsicos de clculo, entonces tenemos la posicin, la primera derivada de la posicin (la velocidad) y la segunda derivada de la posicin (la aceleracin).

5 Ejecuta el proyecto. Rpido! Detente y considera cuan fcil podra adaptarse esa simulacin a un amplio rango de cosas interesantes: por ejemplo el simulador de un sistema solar. Observa lo juntos que empiezan los sprites pero a lo largo del tiempo se van alejando ms y ms. AnimatedSpriteFlock 1 Abre el proyecto AnimatedSpriteFlock. Ejectalo. Advierte la diferencia: los sprites estn animados (cambian de color). Para ello creamos una clase que sustituye la fuente grca del anterior cdigo. Esta nueva clase (AnimatedPicture) contiene uno o ms objetos DirectedPicture. En funcin de la cantidad de tiempo transcurrida, esta pasar una peticin de imgenes en bucle a los objetos que contiene. Por tanto, esta clase contenedora proporciona un recorrido cclico de imgenes basado en el tiempo. 2 Examina el cdigo encargado de llevarlo a cabo Observa lo simple que es! Adems de algn cdigo encargado de la inicializacin y un constructor adicional y un motdo en la clase DirectorChevron (de modo que podamos obtener el color desde otra instancia para denir el colo de su opuesto), los cambios para aadir esta nueva capacidad son realmente directos. Puedes observar como esto es posible gracias a un buen diseo orientado a objetos? La respuesta involucra el uso de polimorsmo y una simplifcacin del paradigma modelovista-controlador. Puedes observar hasta qu punto es un tipo simplicado del diseo MVC? Corregir la velocidad Advierte que si bien los ciclos de animacin estn basados en tiempo, la velocidad a la que funciona la simulacin depende de la cantidad de sprites y de la velocidad del ordenador (esto determina el framerate del SpriteSurface). Hay algunos modos de solucionar esto: ya sea ajustando de forma explcita el framerate del SpriteSurface; separando por completo el modelo y actualizndolo mediante el uso de un temporizador; o dejar que el modelo se encargue de registrar el tiempo transcurrido entre fotogramas, y ejecutar la cantidad de pasos de simulacin necesarios en funcin de la cantidad de tiempo que haya transcurrido. Piensa sobre las ventajas y desventajas de cada uno de ellos. Ejercicios adicionales Este proyecto puede ampliarse de varias formas. Algunas ideas para empezar: Incorpora algunas fsicas adicionales (puedes hacer algo de investigacin en Internet o en libros de texto sobre fsicas para obtener informacin adicional). Algo razonablemente fcil consiste en aadir friccin. Ms complicado es conseguir que los sprites reboten entre s (la opcin fcil: asumir que cada uno es en realdiad un crculo). Este es un buen

punto de partida para pensar sobre fsicas realistas, frente a algo que tenga un aspecto razonable. Crea un simulador del sistema solar. Ya sea uno basado en un sistema solar real, o bien tener un sol central sobre el que estn atraidos el resto de los objetos, y sita unos cuantos objetos con masas aleatorias, posiciones y velocidades y observa como van todos hacia el sol, giran en el espacio o entran en una rbita estable. Resulta razonablemente fcil hacer que el sol sea simplemente una fuente de gravedad; y resulta interesante crear un proyecto donde cada uno de los objetos tenga su propia gravedad. Calcular dicha propiedad tiene que ver con la realizacin de una serie de operaciones proporcionales a N2 para N objetos, de modo que no llevar mucho tiempo para que unos pocos objetos empiecen a ralentizar la simulacin. Crea un juego o juguete como por ejemplo una simulacin de patinaje sobre hielo. Tendrs que investigar sobre otras capacidades del SpriteSurface como por ejemplo la deteccin de colisiones o el escaneado del teclado, pero la investigacin siempre es algo bueno...

Vous aimerez peut-être aussi