En Kotlin, les génériques (paramètres génériques) sont par défaut effacés (type erasure) : au moment de l'exécution, il n'y a pas d'informations sur les types. Cela complique la réflexion, la conversion de types et la lecture des annotations par type. Pour la plupart des tâches, cela est acceptable : les génériques normaux fonctionnent de manière similaire à Java.
Les fonctions inline avec un paramètre reified permettent de "forcer" le compilateur à "substituer" un type spécifique au moment de l'appel, ce qui permet à la fonction d'effectuer des opérations sur le type à l'exécution (par exemple, effectuer des vérifications, créer de nouvelles instances via la réflexion, etc.). Cependant, reified ne peut être appliqué qu'aux paramètres dans les fonctions inline.
Exemple comparatif :
// Générique normal fun <T> printType(t: T) { println(t.javaClass) // Provoquera une ClassCastException pour List<Int> et d'autres. } // avec reified inline fun <reified T> printType(t: T) { println(T::class.simpleName) } fun main() { printType(123) // Affichera : Int printType("hello") // Affichera : String }
Pratique d'application : Le plus souvent utilisé pour vérifier le type, le casting, la réflexion, la création d'instances, où il n'est pas possible d'obtenir le type autrement.
"Une fonction avec un type reified peut-elle ne pas être inline ?"
reified fonctionne uniquement dans les fonctions inline. Sinon, la substitution de type au moment de la compilation est impossible.Exemple d'utilisation incorrecte :
fun <reified T> failFunction() {} // Erreur de compilation : le paramètre de type reified ne peut être utilisé que dans une fonction inline
Correct :
inline fun <reified T> goodFunction() {}
Histoire
Dans un projet, il était nécessaire de parser universellement des chaînes JSON dans n'importe quel type via une fonction avec un paramètre générique. L'implémentation standard via
fun <T> parse(json: String): Tne fonctionnait pas correctement à cause de l'effacement de type — il était impossible d'obtenir Class<T> pour parser des collections et des modèles génériques. On a décidé d'utiliser inline avec un type reified — le problème a disparu.
Histoire
Un des développeurs tentait de créer des instances de type T à l'aide d'un constructeur normal
T(), sans utiliser inline et reified. À la compilation, une erreur est survenue car les informations sur le type avaient été effacées. En réécrivant en tant qu'inline fun <reified T: Any>, il a réussi à résoudre tout avec les moyens standards du langage.
Histoire
En essayant d'utiliser reified dans une fonction normale (sans inline) — l'IDE a donné une erreur de compilation déroutante. Le développeur a longtemps cherché la cause, jusqu'à ce qu'il se penche sur la documentation et corrige la fonction en ajoutant inline.