ProgrammationDéveloppeur Backend

Qu'est-ce que le smart casting en Kotlin ? Comment cela fonctionne-t-il avec les conditions, les expressions when, les types nullable, les getters personnalisés et les propriétés ? Donnez des exemples et des écueils.

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

Smart casting — est un mécanisme par lequel le compilateur Kotlin "abaisse" automatiquement le type après une vérification sur un type ou null spécifique. Cela permet d'utiliser les propriétés et les méthodes de ce type sans conversion explicite.

Exemple :

fun demo(x: Any) { if (x is String) { println(x.length) // x est automatiquement converti en String } }

Fonctionne avec :

  • Les opérateurs is / !is (par exemple, dans if ou when)
  • Les variables nullable (if (x != null))
  • Les expressions when

Ne fonctionne pas :

  • Lorsque la propriété a un getter personnalisé (le compilateur perd confiance que la valeur n'a pas changé entre la vérification et l'utilisation)
  • Pour les propriétés open/var de la classe

Exemple avec nullable:

val str: String? = getString() if (str != null) println(str.length) // smart cast

Quand cela ne fonctionne pas :

val something: Any get() = fetch() if (something is String) { println(something.length) // Erreur : smart cast impossible }

Question piège.

Peut-on compter sur le smart cast pour des propriétés open ou var dans les méthodes ?

Non ! Le smart cast fonctionne uniquement avec des variables locales et des propriétés val dans des classes finales. Pour les propriétés ouvertes (open) ou var, le compilateur n'est pas sûr que la valeur puisse être modifiée par d'autres threads ou par des descendants. Pour celles-ci, un cast manuel ou une variable locale est nécessaire.

open class Base { open var maybeString: Any? = "abc" fun check() { if (maybeString is String) { // println(maybeString.length) // Erreur : Smart cast impossible val asString = maybeString as String println(asString.length) // Cast explicite } } }

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


Histoire

Dans un projet, pour la logique des écrans, des propriétés var open de données modèle étaient utilisées. Le programmeur comptait sur le smart cast après la vérification if (model is SomeType), mais lors de la compilation, il a dû tout convertir manuellement, ce qui a dégradé la lisibilité et a ajouté des duplications de code en raison de l'ignorance de la limite du smart cast sur var/open.


Histoire

Lors de l'obtention de données via un getter (par exemple, via un délégué ou une validation), le smart cast ne fonctionnait pas pour la valeur. Le développeur ne comprenait pas les raisons et a passé plusieurs heures à déboguer jusqu'à ce qu'il réalise que le compilateur n'applique pas le smart cast à de tels getters, car ils peuvent retourner des valeurs différentes entre les appels.


Histoire

Dans un projet, lors du traitement de valeurs nullable via if (obj != null), le smart cast fonctionnait à l'intérieur du bloc, mais lors du parallélisme du code, des NullPointerException apparaissaient à cause des accès en dehors de la zone de garantie. Cela a montré une compréhension insuffisante de l'action locale du smart cast et des spécificités des scénarios multithread avec des variables nullable.