Escribe tu búsqueda

Xojo: Parámetros opcionales, y paso de datos por valor o referencia

Compartir

En la última entrega nos centramos especialmente en una serie de métodos muy especiales: los constructores de las clases, y que nos sirvieron de paso para introducir otros conceptos muy útiles en la programación orientada a objetos, tales como la sobrecarga de métodos (overloading) y la redefinición de métodos (overriding). En esta ocasión seguimos con los métodos pero centrándonos más en las diferentes opciones que tenemos a la hora de pasar los parámetros.

Por ejemplo, en muchos casos nos limitamos a realizar sobrecarga de métodos porque simplemente necesitamos que nuestra clase presente una cantidad variable de parámetros, pero ¿no sería mejor idea mantener la cantidad de métodos a raya y definir alguno de sus parámetros como opcionales? De ese modo, si al invocar el método en cuestión pasamos todos los parámetros o sólo parte de ellos, éste continuará realizando su función sin la necesidad de duplicar el código.

La buena noticia es que el lenguaje de programación Xojo nos proporciona dicha capacidad, de modo que simplemente hemos de marcar el parámetro como ‘optional’ para que al tipo de dato asociado se le asigne su valor por defecto en el caso de que no se pase durante la llamada (por ejemplo, en el caso de los enteros este sería de 0).

Como recordarás, en nuestra clase ‘Persona’ utilizábamos la sobrecarga de métodos en el constructor simplemente porque teníamos la posibilidad de utilizar una construcción del objeto más completa, donde pasábamos junto con el nombre y el apellido una serie de valores adicionales (edad y sexo), y otra más abreviada donde dábamos la posibilidad de crear una instancia del objeto pasando al constructor sólo el nombre y apellido.

Ahora hemos simplificado y dejado nuevamente un único constructor, con la salvedad de que en este caso marcamos los dos últimos parámetros como ‘Optional’. De este modo, en el caso de que no pasemos valores para la edad y sexo en la construcción de la instancia, las propiedades correspondientes tomarán los valores por omisión de ‘0’ en el caso del tipo de dato entero (Integer) y de ‘False’ en el caso del tipo booleano (Boolean).

Algo que has de tener en cuenta a la hora de marcar parámetros como opcionales es que estos han de ocupar las últimas posiciones en el campo de declaración de parámetros para el método en cuestión.

Como puedes ver en la imagen, el código utilizado en el método del constructor no varía mucho de lo que ya conocíamos y de hecho se asignan los diferentes valores, incluyendo los parámetros opcionales, a cada una de las propiedades de la clase.

Para comprobar que todo continúa funcionando como debería, dirígete al evento ‘Open’ de la ventana ‘Window1’ en nuestro proyecto de ejemplo (créalos en caso necesario) e introduce el código mostrado en la siguiente imagen:

Como puedes apreciar, en la primera línea creamos una instancia de nuestra clase ‘Persona’ utilizando el constructor para pasar únicamente tanto el nombre como el apellido, de modo que podamos ver los parámetros marcados como opcionales en acción.

En la segunda línea simplemente nos limitamos a mostrar en una ventana modal todas las propiedades del objeto para constatar que, efectivamente, se hayan asignado los valores por defecto a los parámetros marcados como opcionales.

En este sentido, tres apuntes. El primero es la palabra clave ‘endofline’, y que se encarga de añadir el código de retorno de línea correspondiente a cada una de las plataformas en las que puedas desplegar tu aplicación, sin tener que pararte a pensar cuál debería de ser el código ASCII en función de que se vaya a desplegar bajo OS X, Windows, Linux o bien las tres (o si es preciso concatenar dos códigos ASCII, tal y como ocurre en sistemas Unix como el Mac —por cierto 10 y 13—).

El segundo apunte es el guión bajo (underscore) que puedes ver al final de la segunda línea de código. Este es el carácter que podemos emplear en el Editor de Código de Xojo para partir una línea larga en dos o más partes, de modo que dicho fragmento resulte más legible. Si nos limitásemos a partir la línea sin más utilizando el retorno de carro… obtendríamos un error de sintaxis.

El tercer apunte es el uso de la instrucción condicional ‘If’ y que nos sirve para que nuestro programa haga una u otra cosa en función de que el valor comparado sea cierto (True) o bien falso (False).

En este caso se trata de una forma nueva de aplicar la instrucción como si se tratase de un operador y que se ha introducido recientemente en el lenguaje Xojo. De hecho, personalmente la esperaba como agua de mayo.

Así, si el valor contenido en ‘p.sexo’ se evalúa como falso, se toma la primera parte de la expresión (“hombre”), mientras que si fuese cierta daría como resultado la segunda parte de la expresión (“mujer”).

No te preocupes si no te queda muy claro por el momento, ya llegaremos al uso de las instrucciones condicionales con más detalle en el futuro. (Esta forma de la instrucción ‘If’ es el equivalente al operador ternario de otros lenguajes de programación.)

Pero volvamos a la comprobación, ejecuta la aplicación y deberías de obtener una ventana modal con el mismo mensaje que el mostrado aquí. Efectivamente, la edad (Propiedad Integer) toma el valor por omisión de ‘0’, tal y como era de esperar, de igual modo que ocurre en el caso de la propiedad booleana utilizada como indicativo del sexo (por omisión, ‘False’).

Propiedades con valores por defecto

Como puedes comprobar, ¡hace su función! Pero sería mucho mejor si pudiésemos afinar aun más el comportamiento de las propiedades en un método. Por ejemplo, sería genial si pudiésemos indicar cuál debería de ser el valor a tomar por omisión en el caso de el método no recibiese ninguno para una propiedad determinada. Y es posible.

Volvamos al constructor de nuestra clase ‘Persona’ para ponerlo en práctica. Por ejemplo, indicaremos que el apellido reciba el valor “Sin miedo” en el caso de que no se pase ningún valor durante la llamada del método, también indicaremos que la edad por omisión sea de 18 años si no se indica ningún valor, mientras que el sexo por omisión será el de “hombre” (valor ‘True’).

Para ello, la acción de indicar el valor por omisión para cada uno de los parámetros es tan simple como utilizar el signo igual (‘=’) a continuación del nombre de parámetro e identificador de tipo, y completándolo finalmente con el valor en cuestión. Así la declaración de parámetros para el método constructor quedaría de la siguiente forma:

nombre as String, optional apellido as string = "Sin miedo", optional edad as integer = 18, optional sexo as Boolean = true

Regresa al evento ‘Open’ de la ventana ‘Window1’ y modifica la primera línea del siguiente modo:

dim p as new Persona("javier")

 

Ejecuta la aplicación, y en esta ocasión verás que se han tomado los valores que nosotros hemos asignado para cada uno de los parámetros no recibidos durante la creación de la instancia. Juega con la línea de código completando en mayor o menor medida la cantidad de parámetros pasados durante la construcción.

¿Qué pasaría en este caso?

dim p as new Persona("javier","", 44, true)

Podrías pensar que se trataría el segundo parámetro como un valor no pasado al método, en cuyo caso se aplicaría sobre la propiedad del objeto el valor que hemos especificado por omisión (“Sin Miedo”)… y te equivocarías. Aunque las dobles comillas indican que se trata de una cadena vacía, estaríamos pasando un valor al fin y al cabo, y de hecho sería esa cadena vacía la que se asignaría a la propiedad en cuestión (en este caso el segundo apellido). De modo que si quieres evitar o afinar este tipo de situaciones, será tu responsabilidad utilizar el código adicional en el Constructor para ello.

Sin embargo la moraleja sobre el uso de los parámetros opcionales es la siguiente: en la llamada de un método no puedes elegir qué parámetros serán opcionales y cuáles no. Es decir, en un método que admite un total de cuatro parámetros, tres de ellos marcados como opcionales, no puedes pasar valores nulos en la segunda y cuarta posición, por ejemplo. Para eso debes de acudir a la Sobrecarga de métodos.

Otra cuestión que has de tener en cuenta es que cuando se asignan valores por defecto a determinados parámetros de un método, entonces no es necesario utilizar la palabra clave ‘Optional’ en su declaración. Sin embargo, su uso hace que el código resulte más legible, y por dicho motivo te aconsejo que lo mantengas; pero a efectos prácticos lo siguiente sería igualmente válido:

nombre as String, apellido as string = "Sin miedo", edad as integer = 18, sexo as Boolean = true

Pasar datos por valor o por referencia en los métodos

Para complicar un poco más las cosas, has de tener en cuenta que en muchos casos el valor que llega como parámetro en el método es una copia del valor contenido en la variable original. Por tanto, si dentro del método en cuestión modificas el valor del parámetro, no estarás modificando su valor ‘original’ fuera de dicho método (¿recuerdas los ámbitos y visibilidad de las variables?).

Como de costumbre, se entiende mejor con un ejemplo.

Dirígete al evento ‘Open’ de la ventana ‘Window1’ y sustituye las líneas de código que veníamos utilizando por las siguientes:

Dim nombre as String = "Javier"

dim apellido as string = "Rodriguez"

muestraNombre(nombre, apellido)

MsgBox(nombre + " "+ apellido)

Ahora selecciona el elemento “Window1” en el Navegador de Proyecto y utiliza la combinación de teclas Comando + Opción (Alt) + M para crear un nuevo método dentro de dicho objeto. 

Utiliza la definición de método mostrada en la imagen. Como puedes ver, utilizamos con toda la intención del mundo el mismo nombre para definir los parámetros que los empleados en las variables del evento ‘Open’ (¡visibilidad de variables, cada una en su ámbito de ejecución!). En el Editor de Código correspondiente al método que estamos definiendo, introduce las siguientes líneas:

nombre = nombre + " " + "Juan"

apellido = apellido + " " + "Sin miedo"

MsgBox nombre + " " + apellido

Como ves, estamos modificando los contenidos recibidos en cada uno de los parámetros añadiendo información adicional; un segundo nombre y segundo apellido, si quieres verlo así, para a continuación mostrar el resultado en una ventana modal.

Cuando ejecutes la aplicación verás que la primera ventana muestra el texto: “Javier Juan Rodriguez Sin Miedo”.

Una vez que pulses el botón para cerrar la ventana modal mostrada desde el método, el programa continuará su ejecución en la línea posterior a la llamada de dicho método… donde se muestra una nueva ventana modal con el contenido de las variables ‘Nombre’ y ‘Apellido’ declaradas en esta ocasión en el evento ‘Open’. ¿Cuál será el mensaje mostrado?

“Javier Rodriguez”

Como puedes ver, el método se ha limitado a modificar el contenido de sus variables locales, mientras que las variables externas al objeto, utilizadas en la llamada al propio método, conservan sus valores originales.

En la mayoría de los casos este es exactamente el comportamiento que esperas pero, ¿y si realmente quieres modificar el contenido original? ¿Cómo hacerlo? Pues para esos casos, nada mejor que echar mano de la palabra clave ‘ByRef’ durante la definición de los parámetros del método:

byref nombre as string,  byref apellido as String

Una vez realizado este simple cambio, vuelve a ejecutar la aplicación. En este caso ambas ventanas modales mostrarán los mismos textos, dado que efectivamente el método sí estará modificando el contenido de las variables externas, pasadas como referencia en vez de como valor (ByRef = por referencia).

Una cosa importante que has de tener en cuenta es que todos los tipos primitivos (y las cadenas) se pasan a los métodos como valor por omisión, pero los objetos siempre se pasan por referencia también por omisión, sin necesidad de utilizar la palabra clave ‘ByRef’.

Volvamos a cambiar el código del evento ‘Open’ correspondiente a ‘Window1’ por el siguiente:

dim p as new Persona("Javier", "Rodriguez")

muestraNombre(p)

MsgBox p.nombre + " " + p.apellido

En el método ‘muestraNombre’, cambia la definición de los parámetros por la siguiente línea:

p as Persona

Y por último, sustituye en el Editor de Código de Xojo el contenido del método ‘muestraNombre’ por el siguiente:

  p.nombre = p.nombre + " " + "Juan"

  p.apellido = p.apellido + " " + "Sin miedo"

  MsgBox p.nombre + " " + p.apellido

Ejecuta de nuevo la aplicación, verás nuevamente que ambas ventanas modales muestran el mismo contenido. El método ha modificado los valores del objeto asignado a la variable externa.

¡Colecciones de datos!

Pero los objetos no son los únicos tipos de datos que se pasan por omisión a los métodos por referencia, también es así en el caso de los Arrays (http://docs.xojo.com/index.php/Array) o matrices de datos. Se trata de uno de los tipos disponibles en Xojo para el almacenamiento de colecciones de datos, y este será precisamente uno de los temas de nuestra próxima entrega. Hasta entonces, pon en práctica todo lo visto hasta ahora, y especialmente esta última parte.

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.

1 Comentario

  1. u7200 11 mayo, 2016

    Javier he comenzado a programar en Xojo. (Venia de Basic) y me gustaría preguntarte, si me podrías ayudar. Quiero saber como dar una instrucción al código (en un bucle) para que detecte que he presionado una tecla o el ratón y pause el programa, hasta que vuelva a apretar el ratón.
    Cuando este bucle está corriendo, los botones que modifican el código que corre, no funcionan y solo están disponibles cuando este cesa

Dejar un comentario

Twitter
Visit Us
Tweet
YouTube
Pinterest
LinkedIn
Share