ProgrammationDéveloppeur Android

Expliquez la différence entre les paramètres génériques normaux, inline et reified en Kotlin. Quand et pourquoi utilise-t-on reified, quelles sont les limitations de l'approche générique standard qu'il supprime ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse

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.

Question piège

"Une fonction avec un type reified peut-elle ne pas être inline ?"

  • Non — 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() {}

Exemples d'erreurs réelles dues à une méconnaissance des subtilités du sujet


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): T ne 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.