Xojo: de clases y objetos

En el anterior capítulo hicimos nuestra incursión en el mundo de las variables y los tipos de datos. En este, veremos de qué modo tan sencillo puedes crear tus propios tipos de datos: las clases, y en qué medida están relacionadas las clases con los objetos o instancias de clase. ¡Empieza lo bueno!

Hasta ahora sabemos que las variables pueden contener el tipo de dato que hayamos declarado previamente, y que esto será así siempre que se encuentre en su ámbito de ejecución. Sin embargo hay vida más allá de los números, ya sean enteros o de coma flotante, y de las cadenas (strings) que vimos en el anterior capítulo. Xojo permite crear cualquier nuevo tipo de dato que precises mediante la definición de una Clase.

De hecho, en Xojo ya encontrarás decenas de clases predefinidas y que están listas para usar, desde cualquiera de los controles gráficos que puedes arrastrar y soltar sobre las ventanas (también clases) desde el panel Inspector del IDE, hasta la ristra de clases que puedes emplear para hacer todo tipo de operaciones gráficas, de composición musical, tratamiento de vídeo, acceso a Internet, uso de bases de datos, tratamiento de correo electrónico, cifrado de datos, y un larguísimo etcétera.

Si lo deseas, puedes ver un completo listado de las clases disponibles en Xojo aquí, mientras que en este otro enlace encontrarás la jerarquía de clases utilizada por el framework de Xojo, y que es bueno que vayas teniendo en mente para cuando abordemos un aspecto posterior: la herencia.

¿Qué es una clase?

Una clase no es más que la definición de las propiedades encargadas de almacenar un estado, así como de los métodos encargados de actuar sobre dicho estado. Por ejemplo, probemos a definir una nueva clase ‘Persona’. Esta se encargará de almacenar los principales valores (estado) que pueden identificar a una persona de forma única. Para ello, crea un nuevo proyecto de tipo Escritorio con el IDE de Xojo.

Una vez que aparezca la ventana del Editor, pulsa sobre el botón Insert y selecciona la entrada Class. Cuando sueltes el botón verás que se ha añadido un nuevo elemento en el navegador de proyecto. Selecciónalo y asegúrate de que esté activo el panel Inspector en la parte derecha de la ventana del IDE.

 

En el panel Inspector, introduce el texto “Persona” en el campo ‘Name’. Este será a partir de ahora el nombre de nuestra clase (por ahora nos olvidaremos de los otros dos campos, relacionados con aspectos de herencia de clases que trataremos más adelante: Super e Interfaces).

Sin embargo, por el momento nuestra nueva clase no es nada en absoluto. Carece de propiedades sobre las cuales podamos almacenar su estado, y tampoco presenta ningún método que nos permita modificar dicho estado.

Añadiremos las propiedades: Nombre, PrimerApellido, SegundoApellido, edad y genero. Para ello, selecciona con el ratón la recién creada clase Persona en el navegador de proyecto y dirígete nuevamente al menú Insert para seleccionar, en esta ocasión, la entrada Property (Comando + Opción + P).

Por cada propiedad que introduzcas, verás que el panel Inspector muestra una serie de campos que te permitirán definir el tipo base para la propiedad. Es decir, las propiedades no son más que un tipo especial de variable en la que has de declarar también su tipo, y que están ligadas a la propia definición de clase. Por tanto, las propiedades pueden ser cualquiera de los tipos incluidos de serie en Xojo o bien cualquier otro tipo (definición de Clase) creada por ti.

Llevándolo al caso práctico que nos ocupa, para la propiedad Nombre usaremos los siguientes valores en el panel Inspector:

Name: nombre
Type: String
Default:
Scope: Private

Utiliza esto mismo para añadir las propiedades ‘primerApellido’ y ‘segundoApellido’, variando lógicamente el campo correspondiente a la entrada Name.

A la hora de definir la propiedad ‘edad’, utiliza los siguientes valores:

Name: edad
Type: Integer
Default:
Scope: Private

Mientras que a la hora de añadir la propiedad ‘genero’ utilizaremos un tipo Booleano, de modo que un valor de cierto (True) indique hombre y falso (False) indique mujer (si lo prefieres, invierte la equivalencia de los valores).

En todas estas definiciones habrás observado que el campo ‘Default:’ se ha dejado intencionadamente vacío. Esto es así porque la definición de nuestra pequeña Clase de ejemplo no lo requiere, pero en otros casos podríamos desear que las propiedades utilizasen un valor por defecto en el caso de que no se indicase ninguno, y esa es la función del campo Default. Ahí podremos indicar en cada caso el valor que se utilizará, y que ha de corresponderse con el tipo de dato con el que hayamos declarado la propiedad en cuestión.

Una vez que hayas terminado con la definición de las propiedades éstas deberían de verse como en la imagen.

Ahora nuestra clase ya tiene definidas todas las propiedades encargadas de almacenar su estado (combinación de valores para una entidad única del tipo) pero, ¿cómo asignamos los valores a dichas propiedades? Y más importante aún, si la clase es la declaración de un tipo, ¿cómo hacemos para trabajar con esos nuevos tipos asignándolos a las variables en nuestros programas?

Objectos, las instancias de las Clases

Pues bien, la respuesta a la anterior pregunta es mediante los Objetos. Piensa en la definición de una Clase de Xojo como en la creación de una plantilla, un molde. Ahora, una vez que tienes tu molde terminado y pulido, ya podrás utilizarlo para crear tantas instancias o nuevos objetos como desees de esa misma clase. Todos ellos presentarán en su estructura las mismas propiedades que hayas definido en la clase, así como los métodos que actúen sobre su estado.

Es el momento de crear una nueva instancia de nuestra clase Persona. Para ello, selecciona el icono App y pulsa sobre el icono Insert en la barra superior de la ventana para añadir un nuevo Event Handler (Manejador de Evento). En el panel resultante, selecciona el evento ‘Open’. El código que introduzcamos en dicho evento será el que se ejecute cuando se ponga en marcha la aplicación.

Para crear una nueva instancia de una clase en Xojo utilizaremos la palabra clave ‘New’. Así, la asignación de una nueva instancia de objeto a una variable sería del siguiente modo. En primer lugar declaramos el tipo de la variable, tal y como ya vimos en el anterior capítulo:

dim p as Persona

(Verás que Xojo te facilita mucho las cosas mediante el autocompletado dinámico de texto).

Ahora asignamos una nueva instancia de objeto sobre la variable utilizando la palabra clave ‘New’:

p = new Persona

Sin embargo, estas dos instrucciones pueden acortarse (y de hecho se suele hacer) en una sola:

dim p as Persona = new Persona

E incluso es recomendable utilizar la fórmula más abreviada:

dim p as new Persona

Con nuestra nueva instancia creada y asignada a una variable, es momento de comenzar a asignar los diferentes valores a cada una de las propiedades definidas previamente. Para ello, en Xojo se utiliza lo que se denomina “Notación por punto”. Esto significa que puedes acceder a las propiedades y/o métodos definidos por la Clase mediante el uso del nombre de la variable, seguida por el signo punto, y seguida a continuación por el nombre de la propiedad o método en cuestión. Así, por ejemplo, para asignar la edad a nuestra recién creada instancia utilizaremos la siguiente sintaxis:

p.edad = 18

No continúes con el resto de propiedades. Detengámonos por un momento aquí para ejecutar la aplicación tal y como está. ¿Qué ocurre?

Si todo ha ido bien, habrás recibido el mensaje mostrado en la imagen por parte del compilador. Aquí se indica que no es posible acceder directamente a una propiedad de la clase cuya visibilidad ha sido declarada como ‘Privada’. ¿Qué quiere decir todo esto?

Encapsulación y visibilidad

Lo que significa es ni más ni menos que la primera de las reglas de la programación orientada a objetos y, más concretamente, de la definición de una clase: ningún objeto exterior debe de modificar directamente el estado de otro objeto. El estado del objeto solo es modificable a través de los métodos declarados como públicos por la clase en cuestión.

Si la visibilidad es privada, tal y como debe en el caso de la definición de las propiedades de una clase, significa que sólo los métodos de la propia clase pueden acceder directamente a dichas propiedades.

Para que entiendas mejor la relación entre los diferentes tipos de visibilidad o acceso (Privado, Protegido y Público), volvamos a seleccionar nuestra clase Persona y selecciona cada una de sus propiedades. En esta ocasión, elige la entrada ‘Public’ correspondiente a la entrada ‘Scope’ del panel Inspector para cada una de ellas.

Cuando hayas finalizado, vuelve al evento Open del objeto App y continúa asignando valores al resto de las propiedades:

p.nombre = "Javier"
p.primerApellido = "Rodríguez"
p.segundoApellido = "Menéndez"
p.genero = true

Lo primero que advertirás es que “algo” ha cambiado para bien, dado que ahora también funciona el autocompletado de Xojo cuando escribes el nombre de cada una de las propiedades después del punto. Una muestra más de que en esta ocasión sí está permitido por el compilador (¡aunque sea un lamentable uso de la programación orientada a objetos, rompiendo por completo la encapsulación!)

Ahora que ya sabemos que las propiedades son accesibles desde el exterior si así lo deseamos, volvamos a hacer las cosas bien y cambiemos nuevamente la visibilidad de las propiedades en nuestra clase a ‘Private’.

Por tanto, dado que no es posible acceder directamente a las propiedades… ¿cómo hacemos para asignar valores? Mediante la definición de métodos en nuestra clase.

Creando Métodos

Vuelve a seleccionar la clase Persona y, ahora, accede al menú contextual (Ctrl + clic sobre el icono de la clase Persona) para elegir a continuación la entrada Add to Persona > Method.

Verás que, por omisión, su visibilidad está definida como Private; cámbiala a Public, dado que en este caso queremos definir el método como visible por otros objetos de nuestro proyecto.

Como nombre del método escribe ‘nombre’ (sin las comillas simples). Así sabremos que se trata del método encargado de asignar un valor a la propiedad del mismo nombre. Dado que la propiedad ‘nombre’ es de tipo String, esperamos recibir un atributo del mismo tipo; por tanto declara una variable ‘s as string’ en el campo ‘Parameters’.

Dado que el procesado realizado por este método no devuelve ningún valor, dejaremos vacío el campo ‘Return Type’ y que, de otro modo, declararía el tipo devuelto por nuestro método a quien lo hubiese invocado.

¡Ahora queda lo más importante! En la parte central correspondiente al editor de código, introduciremos el código responsable de realizar la asignación entre el parámetro recibido en nuestra variable ‘s’ (es decir, la cadena de texto pasada a nuestro objeto desde el mundo ‘exterior’), hacia la propiedad interna que en este caso sí es accesible, puesto que estamos trabajando con ella (modificando su estado) desde dentro de la propia clase o de cualquiera de los objetos creados a partir de dicha plantilla.

En esta imagen puedes ver el resto de los métodos ya definidos. Haz lo propio, teniendo en cuenta la definición de tipo que has de emplear en cada caso para el parámetro recibido.

Una vez que hayas finalizado, si intentas ejecutar el programa verás que sigue fallando. Esto es así porque en la llamada y paso de valores sobre los métodos no se utiliza en Xojo por omisión el signo ‘=’; en vez de ello basta con utilizar un espacio como separación o bien encerrar el valor entre paréntesis. Por ejemplo lo siguiente sería válido en el evento Open del objeto App:

  dim p as new persona
  
  p.edad 0
  p.nombre( "Javier" )
  p.primerApellido "Rodriguez"
  p.segundoApellido("Menendez")
  p.genero true

  
Sin embargo, hay casos en los que resulta más natural realizar llamadas a los métodos del objeto pasando los valores mediante la asignación típica; es decir, utilizando el signo igual (‘=’).

En Xojo podemos emplear esta mejora sintáctica durante la declaración del parámetro en la definición de los métodos en cuestión; siempre y cuando el método sólo reciba un parámetro. La palabra clave que debemos de utilizar es ‘assigns’. Por ejemplo, para que la llamada a nuestro método de edad tome la forma de asignación, utilizarmos lo siguiente en el campo Parameteres desde el panel Inspector:

assigns n as Integer

Ahora ya podemos utilizar la fórmula de asignación convencional:

  dim p as new persona
  
  p.edad = 0 // ¡Ahora ya podemos llamar al método pasando un parámetro como si fuese una asignación de variable!
  
  p.nombre( "Javier" )
  p.primerApellido "Rodriguez"
  p.segundoApellido("Menendez")
  p.genero true

  
Prueba a hacer lo mismo en el resto de los casos.

Ahora bien, hasta ahora solo hemos resuelto la primera parte en el uso de las propiedades de nuestra clase. Ya sabemos como asignar valores a las propiedades para cada nuevo objeto creado a partir de la clase pero, ¿cómo hacemos para recuperarlos? Obviamente, declarando nuevos métodos.

En este caso, no requerimos de la definición de parámetros puesto que no esperamos ningún dato de entrada cuando se llame a dicho método (en ciertas clases, sí es así), sino que la parte importante consiste en declarar el tipo devuelto y… devolverlo a quien haya invocado el método del objeto.

Por tanto, crea tantos nuevos métodos como propiedades tiene nuestra clase, y en este caso precede el nombre de cada método con la partícula ‘get’, de modo que quien los use sepa que va a recibir un valor al invocarlo. Por ejemplo, para obtener el valor almacenado en la propiedad ‘nombre’ sería así:

Method name: getNombre
Parameters:
Return Type: string
Scope: Public

Y en el Editor de código, esta simple línea:

Return nombre

Es decir, la palabra clave ‘Return’ indica que se va a devolver el valor almacenado en la propiedad ‘nombre’ a quien haya invocado el método en cuestión. Sabido esto, completa los métodos para obtener el resto de las propiedades.

La Clase “finalizada” debería de tener el aspecto mostrado por la imagen.

Como puedes ver, resulta una labor bastante ardua el hecho de crear simplemente los métodos para definir los valores de las propiedades y para obtenerlos (conocidos comúnmente como setters y getters). Debe de existir una forma mejor si lo único que deseamos es simplemente hacer eso, asignación y devolución de valores sin más con nuestras propiedades, sin ningún otro tipo de procesado o con el procesado adicional de los valores recibidos y/o devueltos.

Propiedades Calculadas

¡Y lo hay! Selecciona todos los métodos creados hasta ahora y bórralos, sin piedad. ¿Trabajo perdido? En absoluto, hasta ahora has visto cómo definir nuevos métodos, como pasar valores a dichos métodos y asignarlos a las propiedades del objeto, además de devolver valores desde la instancia de clase hacia otros objetos o variables que hayan invocado el método en cuestión. Pero ahora vamos a ver la forma óptima en Xojo de crear métodos setters y getters asociados a las propiedades, en un abrir y cerrar de ojos.

Selecciona la propiedad ‘nombre’ en nuestra clase Persona y, en esta ocasión, accede al menú contextual (Ctrl + clic sobre el icono de la propiedad ‘nombre’) para elegir por último la entrada Convert to Computed Property. Como resultado, verás que se ha asociado una flecha de desglose a la propiedad ‘nombre’. Lo que quizá no veas a la primera es que dicho grupo tiene una visibilidad pública, mientras que se ha añadido una nueva propiedad (con una ‘m’ al principio del nombre original) y que mantiene la visibilidad definida originalmente.

Haz clic sobre dicha flecha y verás que Xojo ha añadido por ti un par de métodos (Get y Set) asociados con dicha propiedad, elige cada uno de ellos y verás que cuentan con la definición de método y el código correspondiente para cumplir su función. ¡Incluso funcionan con la sintaxis de asignación convencional! No es preciso que utilices la palabra clave ‘assigns’ en la definición de los parámetros del método.

Nuestra clase en acción

Ha llegado el momento de poner nuestra clase en acción. Diseñaremos una ventana como una plantilla básica de creación de registro de personas, lógicamente utilizando nuestra flamante clase Persona.

Borra todo el código introducido en el evento Open del objeto App, y diseña tu ventana del proyecto para que tenga un aspecto similar al mostrado en la imagen. Aquí hemos utilizado los siguientes controles: ListBox (control de listado), TextField (control de introducción de texto), Label (para las etiquetas de texto) y PushButton (botón de creación de registro). Cambia los nombres de los controles por los siguientes:

TextField, name: Nombre
TextField, name: PrimerApellido
TextField, name: SegundoApellido
TextField, name: edad
CheckBox, name: Genero

A continuación, selecciona la entrada Window1 en el navegador de Proyecto y añade una nueva propiedad en la ventana (visibilidad: Private) con los siguientes datos:

Name: Personas()
Typ: Persona

Añadiendo un paréntesis de apertura y cierre en el nombre de propiedad indicamos que se trata de un Array de tipo Persona. Es decir, esta propiedad contendrá una lista de objetos de nuestra clase.

A continuación añade un nuevo método en la ventana con el nombre ‘creaRegistro’ y el siguiente código:

  dim p as new Persona
  
  p.nombre = nombre.Text
  p.primerApellido = primerApellido.Text
  p.segundoApellido = segundoApellido.Text
  p.edad = val(edad.Text)
  
  p.genero = if(genero.Value, true, false)
  
  Personas.Append p
  
  Listbox1.AddRow( p.nombre + " " + p.primerApellido + " " + p.segundoApellido )

  
Con lo que llevamos visto en el curso de Xojo hasta ahora, deberías de ser capaz de saber qué hace este código, salvo por la instrucción ‘if’. Esta se trata de una instrucción condicional que comprueba el valor devuelto por el primer componente (en este caso genero.value). Si se evalúa como cierto, se devuelve el segundo componente (True), si se evalúa como falso, se devuelve el último componente (False).

Por último, añade un evento Action a nuestro PushButton (Comando + Opción + E). Una vez añadido introduce la siguiente línea de código en dicho evento:

creaRegistro

Es decir, cada vez que pulsemos sobre el botón éste llamará al método ‘creaRegistro’ donde se creará una nueva instancia de la clase Persona y se asignarán a sus propiedades los datos recogidos en nuestro formulario, añadiéndola a la propiedad array encargada de guardar todas nuestras nuevas instancias y añadiendo por último al control ListBox el resultado de concatenar el nombre y los apellidos de la instancia.

¿Por qué es necesario guardar las instancias creadas en el array Personas? Por lo que ya sabemos sobre las variables, ámbito y ciclo de vida. Es decir, cuando nuestro programa entre en el método ‘creaRegistro’ se crea una nueva variable ‘p’ de tipo ‘Persona’ y se le asigna una nueva instancia de dicha clase. Pero cuando la aplicación finaliza con la ejecución del código existente en dicho método se destruirán todas las variables utilizadas en él. Por tanto, el ámbito de la variable ‘p’ está limitado al método y su ciclo de vída es válido mientras que el programa esté “dentro” de dicho método, una vez que salga… se destruirá y por tanto también se destruirá el objeto creado y que es referenciado por dicha variable. Es como si al entrar en el método ‘crearRegistro’ hubiésemos cogido una hoja de papel, hubiésemos escrito nuestros datos en ella, y la hubiésemos arrojado a una trituradora al salir del método.

Ahora bien, la propiedad de lista ‘Personas’ tiene una vida mucho mayor, dado que continuará presente siempre que también esté presente el objeto de ventana ‘Window1’ que la contiene. Así, cuando añadimos nuestro recién creado objeto ‘p’ a dicho array, éste continuará manteniendo una referencia sobre él y, por tanto, seguirá vivo y podremos seguir accediendo a sus datos. Es como si en el método ‘crearRegistro’ hubiésemos decidido guardar la hoja cumplimentada con nuestros datos en una carpeta en vez de arrojarla a la trituradora de papel.

Una vez realizada dicha aclaración, ha llegado el momento de ejecutar la aplicación y probarla. ¡Funciona!

Ahora prueba a modificar y mejorar el programa y repasa los métodos y propiedades asociados a las clases de Xojo que hemos visto hasta ahora.

Enlaces de Interés sobre Xojo

Artículos anteriores

Javier Rodríguez (@bloguintosh) es desarrollador OS X e iOS, director de Macsoluciones.com. Puedes contactar con él para el desarrollo de aplicaciones para Mac e iOS en entornos empresariales así como consultoría y formación.

Javier Rodríguez

Javier Rodríguez (@bloguintosh) es desarrollador y autor del eBook "Programación Multiplataforma Xojo". Puedes contactar con él para el desarrollo de aplicaciones y soluciones multiplataforma, así como consultoría y formación en www.aprendexojo.com

0 0 votos
Article Rating
Subscribe
Notify of
3 Comments
Oldest
Newest Most Voted
Opiniones Inline
Ver todos los comentarios
jocoloso
10 years ago

Por si a alguien le interesa, acabo de recibir un correo de MacHeist con su nuevo “bundle”, el Apple Design Award Bundle, que incluye Xojo Desktop. Eso sí, por ahora está bloqueado, hacen falta 10,000 compras para desbloquearlo.

Ojo, no es el Pro, es el Xojo Desktop, para aplicaciones en OSX, Linux y Windows

http://macheist.com

PD: No tengo ninguna relación ni interés con MackHeist, tan sólo creo que visto el ahorro, sólo por este programa ya merece la pena.

Saludos 😉

Luis Ge Le
Luis Ge Le
10 years ago

Gracias Jocoloso. Yo me descargué el Bundle hace 2 días por 3 aplicaciones que me interesaban. Ya van más de 8.000 descargas y quedan 4 dias. Seguro que se llega a las 10.000 y se desbloquea Xojo. La verdad que es el programa de mayor valor del Bundle. Y parece muy interesante. Javier está haciendo un tutorial medio para novatos medio para iniciados que pica la curiosidad.

Luis Ge Le
Luis Ge Le
10 years ago

Ah, en realidad el IDE de Xojo es gratuito. Lo que te venden es una licencia para compilar y desplegar tus aplicaciones creadas con Xojo, a parte del soporte. Concretamente la del Bundle te permite compilar para OS X, Windows y Linux, como has señalado.

3
0
Me encantaría saber tu opinión, por favor, deja un comentariox
()
x