Constructores en Xojo

Puedes crear completas aplicaciones, de principio a fin, sin tan siquiera sentir la necesidad de utilizar estos métodos tan especiales en la creación de tus propias clases, e incluso en una amplia mayoría de las que se incluyen de serie en el propio framework de Xojo. Ahora bien, si te pica la curiosidad y continúas leyendo… igual la próxima vez decides implementar un Constructor, o dos… ¡o más! en el diseño de tus próximas clases Xojo.

¿Qué es un Constructor, después de todo? Bien, de encontrarse en la definición de la clase, este será el primero de los métodos que ejecute su código cada vez que creemos una nueva instancia (objeto) a partir de dicha clase. Es decir, cada vez que utilicemos la palabra clave New, como por ejemplo:

Dim miNuevoObjeto as New MiClase

Si la clase MiClase carece de método Constructor, no pasa nada; el compilador de Xojo tirará del constructor que comparten por omisión todos los objetos. Recuerda, el lenguaje de programación Xojo es orientado a objetos… y esto significa que absolutamente todos ellos heredan de una clase padre o nodo común (Object en el caso de Xojo), tanto si lo defines explícitamente como si no. Ahora bien, pongamos por caso que tenemos una clase Persona que contiene las propiedades públicas nombre, apellido y dirección con la siguientes definiciones:

  • nombre as text
  • apellido as text
  • direccion as PostalAddress

Observa que la tercera de las propiedades, direccion contiene valores del tipo (objetos de clase) PostalAddress; de modo que hemos de definirla creando una nueva clase en nuestro proyecto de ejemplo y que se limitará a tener una propiedad pública:

  • postalAddress as text. Introduce el texto “Sin dirección conocida” en el campo Default.

Ahora, en nuestra aplicación de ejemplo y sin que hagamos uso de constructores podríamos hacer lo siguiente:

Dim p as New Persona
Dim pa as New PostalAddress
p.nombre = "Juan"
p.apellido = "Sin Miedo"
p.direccion = pa

¿No sería más conveniente que nuestras instancias Persona contuviesen una dirección, nombre y apellido por defecto? De acuerdo, puedes hacerlo sin mayo problema sin necesidad de recurrir a los Constructores, utilizando por ejemplo el panel Inspector e introduciendo valores por omisión… siempre y cuando se limiten a valores de tipos básicos como son los numéricos o de cadena y texto, pero no cuando se trata de asignar un objeto por omisión como es el caso de la dirección postal. Bien, centrémonos en el ejemplo y veamos como podemos conseguirlo mediante el uso de un método Constructor.

Seleccionando nuestra clase Persona sólo tendremos que añadir un nuevo método para, a continuación, introducir Constructor en el campo Method Name del Panel Inspector asociado. Lo primero que observarás es que, en este mismo panel, desaparece el campo de tipo devuelto asociado a la creación de cualquier método. Después de todo ya sabemos lo que tiene que devolver el constructor de la clase, ¿cierto?: ¡una instancia de la clase!

Ahora, en el Editor de Código asociado con el método Constructor podríamos escribir un código como el siguiente:

me.nombre = "Juan"
me.apellido = "Sin Miedo"
me.direccion = New PostalAddress

A partir de aquí, podríamos reducir el código para la creación de nuevas instancias mostrado anteriormente a la siguiente línea, consiguiendo el mismo resultado:
Dim p as New Persona

Sobrecarga de Constructores

Ahora bien, ¿no sería más conveniente incluso que pudiésemos pasar a nuestro Constructor de clase el nombre y apellido que queremos usar en cada nueva instancia creada? ¡No hay problema! Después de todo, el Constructor de clase es un método más, y por tanto también podemos aplicar overloading o sobrecarga de métodos en la definición de la clase; esto es, cuando varios métodos tienen el mismo nombre pero difieren en la cantidad de parámetros y/o tipos de parámetros recibidos. Por tanto, bastará con volver a seleccionar nuestra clase Persona, añadiendo un nuevo método con el nombre Constructor salvo que, en este caso, cumplimentaremos el campo Parameters con la siguiente información:

  • tNombre as Text
  • tApellido as Text

E introduciremos el siguiente código en el Editor de Código asociado con el método:

me.constructor
if tNombre <> "" then me.nombre = tNombre
if tApellido <> "" then me.apellido = tApellido

Observa especialmente la primera línea: ¡sí, puedes llamar a otro constructor (tal y como harías con cualquier otro método) desde el constructor que se esté ejecutando! Así, nos garantizamos que el objeto se inicializará correctamente ejecutando el Constructor designado (en este caso, inicializando correctamente el objeto correspondiente a la dirección postal). Por tanto, ahora podríamos utilizar cualquiera de las dos versiones para la instanciación de objetos a partir de la clase Persona:

Dim p as New Persona // Con parámetros por omisión
Dim p1 as New Persona("Javier", "Rodriguez") // Pasando valores por omisión durante la creación del objeto.

Bien, sería fantástico que también pudiésemos pasar un objeto de dirección postal a nuestro constructor después de todo, ¿cierto? Seguro que ya sabes cómo:

  • Creamos un nuevo método Constructor.
  • Definimos los Parámetros recibidos como tNombre As Text, tApellido as Text, tDireccion as PostalAddress.

E introduciremos el siguiente código en el Constructor propiamente dicho:

me.constructor(tName, tApellido)
if tDireccion <> nil then me.direccion = tDireccion

Eso es, no sólo podemos invocar o encadenar llamadas a métodos constructores sino que también podemos pasarles parámetros. Después de todo, ¿por qué duplicar código? Ahora, ya podremos instanciar objetos Persona utilizando cualquiera de los Constructores definidos, con la seguridad de que siempre se ejecutará el Constructor designado de la clase:

Dim p as New Persona // Con parámetros por omisión
Dim p1 as New Persona("Javier", "Rodriguez") // Pasando valores durante la creación del objeto.
Dim pa as New PostalAddress
pa.postalAddress = "Hogar, dulce hogar"
Dim p3 as New Persona("Javier", "Rodriguez", pa) // Aportando todos los valores admitidos por la clase: nombre, apellido y dirección

Constructores y herencia de clase

Ahora bien, pongamos por caso que creamos una nueva clase Actor que desciende o hereda (subclase) de la clase Persona definida. ¿Podrías avanzar el comportamiento de la siguiente línea?

Dim ac as New Actor
MsgBox ac.nombre + " " + ac.apellido + endofline + endofline + ac.direccion.postaladdress

Efectivamente, al heredar de la clase Persona heredará sus propiedades y métodos incuyendo también los constructores. ¿qué pasará si decidimos añadir un Constructor propio a la clase Actor?

// Calling the overridden superclass constructor.
// Note that this may need modifications if there are multiple constructor choices.
// Possible constructor calls:
// constructor() -- From Persona
// constructor(tname as text, tapellido as text) -- From Persona
// constructor(tName as text, tapellido as text, tDireccion as PostalAddress) -- From Persona
Super.Constructor

En efecto, el IDE de Xojo se encarga de incorporar por nosotros la necesidad de llamar al constructor de la clase de la cual se hereda (de modo que el objeto se inicie correctamente) y, tal y como es el caso, también nos mostrará todos los constructores disponibles en la clase superior para que seamos nosotros quienes decidamos a cuál de ellos es más conveniente llamar.

Conclusiones

Como puedes observar, los constructores de clase son muy convenientes y conviene definirlos para proporcionar una mayor flexibilidad y también legibilidad a nuestro código, amén de una mayor encapsulación. En este ejemplo todas las propiedades estaban definidas como públicas para facilitar la explicación, pero recuerda que lo recomendable es que no sea así.

Por supuesto, puedes aprender más del lenguaje de programación Xojo y de la Programación Orientada a Objetos desde cero con el eBook “Programación Multiplataforma Xojo“.

Espero que hayas encontrado interesante este artículo, ¡y quedo como siempre a la espera de los comentarios o aportaciones que desees realizar!

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *