En Kotlin, los genéricos (parámetros genéricos) por defecto se eliminan (type erasure): durante la ejecución, no hay información sobre los tipos. Esto complica la reflexión, la conversión de tipos y la lectura de anotaciones de tipo. Para la mayoría de las tareas, esto es aceptable: los genéricos normales funcionan de manera similar a Java.
Las funciones inline con el parámetro reified permiten "forzar" al compilador a "insertar" un tipo específico en el lugar de la llamada, lo que permite que la función realice operaciones con el tipo en tiempo de ejecución (por ejemplo, hacer verificaciones, crear nuevas instancias utilizando la reflexión, etc.). Sin embargo, reified solo se puede aplicar a parámetros en funciones inline.
Ejemplo de comparación:
// Genérico normal fun <T> printType(t: T) { println(t.javaClass) // Lanzará ClassCastException para List<Int> y otros. } // con reified inline fun <reified T> printType(t: T) { println(T::class.simpleName) } fun main() { printType(123) // Imprimirá: Int printType("hello") // Imprimirá: String }
Práctica de aplicación: Se utiliza con más frecuencia para la verificación de tipos, casting, reflexión, creación de instancias, donde no se puede obtener el tipo de otra manera.
"¿Puede una función con tipo reified no ser inline?"
reified solo funciona en funciones inline. De lo contrario, no se puede sustituir el tipo en tiempo de compilación.Ejemplo de uso incorrecto:
fun <reified T> failFunction() {} // Error de compilación: reified type parameter can only be used on an inline function
Correcto:
inline fun <reified T> goodFunction() {}
Historia
En el proyecto, fue necesario parsear de manera universal cadenas JSON en cualquier tipo a través de una función con parámetro genérico. La implementación estándar a través de
fun <T> parse(json: String): Tno funcionaba correctamente debido a la eliminación de tipos — no se podía obtener Class<T> para parsear colecciones y modelos genéricos. Se decidió hacerlo a través de inline con tipo reified — el problema desapareció.
Historia
Uno de los desarrolladores intentaba crear instancias del tipo T utilizando un constructor normal
T(), sin usar inline y reified. En el momento de la compilación se producía un error, ya que la información sobre el tipo había sido eliminada. Reescribiendo como inline fun <reified T: Any> se logró resolver todo con los medios estándar del lenguaje.
Historia
Al intentar usar reified en una función normal (sin inline), la IDE dio un error de compilación confuso. El desarrollador buscó la causa durante mucho tiempo hasta que estudió la documentación y corrigió la función añadiendo inline.