Uno de los pilares de la programación orientada a objetos (POO) es la Introspección. Es decir, la capacidad para acceder a la información y estructura interna de un objeto en tiempo de ejecución. Como sabes, Xojo es un lenguaje de programación orientado a objetos moderno y, como tal, la capacidad de introspección está contemplada de principio a fin.
¿Y para qué querrías utilizar la introspección en tiempo de ejecución? Un buen ejemplo es el que se puede encontrar en la documentación proporcionada por el fabricante, y que permite reducir en gran medida el peso (tamaño) del proyecto, al tiempo que también se gana en flexibilidad dado que permite abordar arquitecturas en las que no se requiera tocar partes del código cuando se produzcan nuevos casos (o excepciones).
Otros casos son los que nos permitirían crear capacidades como la generación de nuevos objetos en tiempo de ejecución derivados de situaciones que pueden cambiar en función de los caminos que vaya tomando el programa (dinamismo).
Personalmente, uno de los últimos casos en los que he recurrido al uso de la introspección en un proyecto Xojo ha sido en combinación con un filtro de búsqueda y donde también se hace uso de los delegados.
Como sabes, con el uso de los delgados se pierde todo tipo de información sobre el objeto que registra un método, de modo que si necesitamos “discriminar” sobre qué objetos debemos de invocar un método o no en función del filtro establecido… tenemos un caso de libro para el uso de la introspección:
Select case hitItem.Text
case "All"
me.filterMode = me.kAll
case "Notes"
dim r as Introspection.TypeInfo
r = Introspection.GetType(me.TrueWindow)
dim s as string = r.BaseType.name
me.filterMode = s
case "Marks"
dim r as Introspection.TypeInfo
r = Introspection.GetType(markbase1)
me.filterMode = r.BaseType.name
end
Otro caso podría ser el de discriminar objetos de una misma clase atendiendo al nombre que adquiere dicho objeto en tiempo de ejecución, y que solo podremos obtener mediante el sistema de Introspección, más allá de los índices de controles o comparaciones de clase y pertenencia a jerarquías de clase, extremos que resultarían demasiado genéricos.
Por último, la introspección también supone una base sobre la cual se puede montar un sistema de TDD para nuestras clases de Xojo o bien de generación de informes de bugs para nuestras aplicaciones (en estos casos, cuanta más información sobre el estado de los objetos en tiempo de ejecución… ¡mucho mejor a la hora de hallar y depurar los bugs!).
Un módulo para todas las clases
El sistema de Introspección en Xojo gira en torno a un Módulo cuyo ámbito de visibilidad es público. A diferencia del ámbito de visibilidad global (aplicado a métodos, propiedades y módulos), esto significa que el acceso a todas las clases que contiene debe de realizarse utilizando la notación por punto: Introspection.clase
Sobre el tipo de información al que se puede acceder, gira en torno a un total de siete clase, siendo MemberInfo la superclase de cinco de ellas, y en la que encontraremos una propiedad que nos da acceso al nombre del tipo de dato sobre el que queramos obtener información: name. Además de la anterior, con el resto de propiedades podremos saber si las propiedades del objeto en cuestión son públicas, privadas o protegidas.
El único método que presenta, getAttributes es el que nos facilita la obtención de un array de objetos AttributeInfo para el objeto en cuestión. Dichos atributos son los que presenta el IDE de Xojo en el panel Inspector a través de la pestaña Atributtes para cada uno de los objetos seleccionados. Así, es posible consultarlos y actuar sobre ellos en tiempo de ejecución.
Del resto de las clases disponibles en el sistema de Introspección, encuentro tremendamente útiles las correspondientes a ConstructorInfo y MethodInfo.
La primera de ellas nos permite crear instancias de objeto mediante el sistema de introspección, utilizando finalmente el método Invoke y utilizando en cada caso la cantidad y tipo de parámetros que sea preciso (información que también podemos extraer utilizando el resto de propiedades de la clase).
Esto mismo es lo que también se puede hacer utilizando la clase MethodInfo, en este caso para cualquiera de los métodos definidos en la clase del objeto en cuestión.