Smart casting es un mecanismo en el que el compilador de Kotlin automáticamente "baja" el tipo después de la verificación de un tipo específico o null. Esto permite utilizar propiedades y métodos del tipo al que se hizo el casting sin necesidad de una conversión explícita.
fun demo(x: Any) { if (x is String) { println(x.length) // x se convierte automáticamente a String } }
Funciona con:
is / !is (por ejemplo, en if o when)if (x != null))whenNo funciona:
val str: String? = getString() if (str != null) println(str.length) // smart cast
val something: Any get() = fetch() if (something is String) { println(something.length) // Error: smart cast no es posible }
¿Se puede contar con el smart cast para propiedades open o var de una clase dentro de métodos?
¡No! El smart cast solo funciona con variables locales y propiedades val en clases final. Para propiedades abiertas (open) o var, el compilador no está seguro de si el valor puede cambiar por otros hilos o subclases. Para ellos se requiere un casting manual o una variable local.
open class Base { open var maybeString: Any? = "abc" fun check() { if (maybeString is String) { // println(maybeString.length) // Error: Smart cast no es posible val asString = maybeString as String println(asString.length) // Casting explícito } } }
Historia
En un proyecto, para la lógica de pantallas se usaron propiedades var open del modelo de datos. El programador confiaba en el smart cast después de la verificación if (model is SomeType), sin embargo, durante la compilación tuvo que convertir manualmente todos los tipos, lo que empeoró la legibilidad y aumentó la duplicación de código debido al desconocimiento de la limitación del smart cast en var/open.
Historia
Al obtener datos a través de un getter (por ejemplo, mediante un delegado o validación), el smart cast no funcionó para el valor. El desarrollador no entendió las razones y gastó varias horas haciendo depuración hasta que descubrió que el compilador no aplica smart cast a tales getters, ya que pueden devolver valores diferentes entre llamadas.
Historia
En un proyecto, al manejar valores anulables a través de if (obj != null), el smart cast funcionaba dentro de la rama, pero al paralelizar el código aparecían NullPointerException debido a accesos fuera del área de garantía. Esto mostró un entendimiento insuficiente sobre el alcance local del smart cast y las particularidades de los escenarios multihilo al trabajar con variables anulables.