Reflexión e introspección en Kotlin: cómo mirar dentro de tu propio código
\n\nImagina que eres un programador que escribe código que se analiza a sí mismo. ¿Suena a ciencia ficción? En el mundo de Kotlin, esto es una realidad. La reflexión y la introspección son esas herramientas que transforman tu código de un simple ejecutor a un verdadero meta-programador. Si alguna vez quisiste obtener información sobre clases dinámicamente, llamar métodos por nombre o trabajar con anotaciones en tiempo de ejecución, este artículo es para ti.
\n\nAnalizaremos cómo Kotlin, al ser un lenguaje que funciona sobre la JVM, utiliza la reflexión, y cómo con ejemplos simples podrás añadir magia a tus proyectos. ¡Vamos allá!
\n\n¿Qué son la reflexión y la introspección? La diferencia que debes conocer
\n\nAntes de sumergirnos en el código, aclaremos los términos. A menudo se confunden estos conceptos, pero hay una línea sutil entre ellos.
\n\n- \n
- Introspección — es la capacidad de un programa de "mirarse a sí mismo". Puedes obtener información sobre la estructura de las clases: qué propiedades, métodos y constructores tienen. Es como abrir el capó de un coche y ver qué hay dentro. \n
- Reflexión — es algo más potente. No solo miras, sino que también cambias el comportamiento del programa durante la ejecución. Puedes llamar métodos que no conocías en tiempo de compilación, crear objetos a partir del nombre de una clase en forma de cadena. \n
En Kotlin, la reflexión está estrechamente relacionada con la reflexión de la JVM, pero tiene sus propias API específicas de Kotlin (por ejemplo, KClass, KFunction). Y sí, para trabajar con reflexión necesitarás añadir una dependencia en tu build.gradle.kts:
dependencies {\n implementation("org.jetbrains.kotlin:kotlin-reflect:1.9.22")\n}\n\n\nSin ella, solo podrás usar las capacidades básicas, como javaClass. Pero para una experiencia completa de Kotlin, instala la biblioteca.
KClass: tu herramienta principal de introspección
\n\nEn Java estamos acostumbrados a Class<?>. En Kotlin, su análogo es KClass. Es el punto de entrada al mundo de la reflexión. Puedes obtener un KClass de dos maneras:
// Forma 1: a través del objeto de clase\nval myClass: KClass<String> = String::class\n\n// Forma 2: a través de una instancia\nval str = "¡Hola, mundo!"\nval classFromInstance: KClass<out String> = str::class\n\n\nAhora tienes acceso a un montón de información: nombre de la clase, paquete, constructores, propiedades, funciones. Veamos un ejemplo:
\n\ndata class User(val name: String, val age: Int)\n\nfun main() {\n val kClass = User::class\n println("Nombre de la clase: ${kClass.simpleName}") // User\n println("Paquete: ${kClass.qualifiedName}") // com.example.User\n println("Número de propiedades: ${kClass.memberProperties.size}") // 2 (name, age)\n \n kClass.memberProperties.forEach { prop ->\n println("Propiedad: ${prop.name}, tipo: ${prop.returnType}")\n }\n}\n\n\nEsto es introspección pura en Kotlin — simplemente estamos observando la estructura. Sin ningún cambio de comportamiento.
\n\nObteniendo información sobre funciones y constructores
\n\nA veces necesitas saber qué métodos tiene una clase, o incluso llamarlos. Para ello usamos KFunction.
class Calculator {\n fun add(a: Int, b: Int): Int = a + b\n fun multiply(a: Int, b: Int): Int = a * b\n}\n\nfun main() {\n val calcClass = Calculator::class\n println("Funciones de la clase Calculator:")\n calcClass.memberFunctions.forEach { func ->\n println(" - ${func.name} (parámetros: ${func.parameters})")\n }\n}\n\n\nLa salida será algo así:
\nFunciones de la clase Calculator:\n - add (parámetros: [a, b])\n - multiply (parámetros: [a, b])\n\n\nReflexión en acción: llamando métodos y creando objetos
\n\nY ahora lo más interesante: la reflexión. Supongamos que tienes una cadena con el nombre de un método,