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.
fun demo(x: Any) { if (x is String) { println(x.length) // x est automatiquement converti en String } }
Fonctionne avec :
is / !is (par exemple, dans if ou when)if (x != null))whenNe fonctionne pas :
val str: String? = getString() if (str != null) println(str.length) // smart cast
val something: Any get() = fetch() if (something is String) { println(something.length) // Erreur : smart cast impossible }
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 } } }
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.