«¡Pero si acabo de comprobarlo!» — el dolor familiar de todo desarrollador Kotlin
\nEstás escribiendo en Kotlin, disfrutando de su concisión y seguridad, cuando de repente — una línea ondulada roja. El compilador muestra: Smart cast to 'Type' is impossible, because 'variable' is a mutable property that could have been changed by this time. ¿Te suena? Si alguna vez te has encontrado con este error, no estás solo. Esta pregunta es una de las más populares en Stack Overflow, y con razón: plantea un tema fundamental: cómo Kotlin nos protege de nosotros mismos.
En este artículo no solo analizaremos por qué ocurre el error, sino que también mostraremos cómo evitarlo elegantemente en 2025. Aprenderás qué es el smart cast (conversión inteligente), por qué Kotlin no confía en las propiedades mutables, y cuáles son las mejores prácticas que te ayudarán a escribir código limpio y seguro sin «parches» innecesarios. ¡Allá vamos!
\n\n¿Qué es el smart cast y por qué es «inteligente»?
\nUna de las grandes fortalezas de Kotlin es la conversión inteligente de tipos. Esto ocurre cuando el compilador entiende por sí mismo que, después de verificar el tipo de una variable, se puede usar como ese tipo, sin necesidad de una conversión explícita. Por ejemplo:
\nfun printLength(obj: Any) {\n if (obj is String) {\n // Smart cast: obj automáticamente se convierte en String\n println(obj.length)\n }\n}\nBonito, ¿verdad? El compilador ve: «Ajá, hemos comprobado que obj es un String, entonces dentro del bloque if es definitivamente una cadena, se puede llamar a length». Esto es el smart cast.
\nPero hay un detalle: este truco solo funciona si el compilador puede garantizar que la variable no cambiará entre la comprobación y el uso. Pero si la variable es var (mutable), no hay garantías. Y aquí empieza la diversión.
La raíz del problema: mutable property (propiedad mutable)
\nVeamos un ejemplo típico que provoca el error:
\nclass UserRepository {\n var currentUser: User? = null\n\n fun printUserName() {\n if (currentUser != null) {\n // ¡Error! Smart cast to 'User' is impossible\n // porque currentUser es var y podría haber cambiado\n println(currentUser.name)\n }\n }\n}\n¿Cuál es el problema? ¡Acabamos de comprobar que currentUser no es null! El compilador responde: «Amigo, estás usando var. Esto significa que entre la comprobación y la llamada a println, otro hilo (o incluso este mismo código en otro lugar) podría haber cambiado currentUser de vuelta a null. No puedo arriesgarme — ¿y si ocurre un NPE?».
¡Y esto es correcto! Kotlin es un lenguaje con filosofía null-safe. No te permite dispararte en el pie. Incluso si estás seguro de que nadie cambiará la propiedad, el compilador se cubre las espaldas. Esto es mejor que tener que lidiar con un NullPointerException en tiempo de ejecución.
¿Cómo solucionarlo? 5 formas probadas (edición 2025)
\nLa buena noticia: hay varias soluciones, y todas son sencillas. Elige la que mejor se adapte a tu estilo de código y a la situación.
\n\n1. Copia local inmutable (la más fiable)
\nLa forma más directa es guardar el valor en un val (variable local inmutable). El compilador ve inmediatamente que el val local no será modificado por nadie, y el smart cast funciona:
fun printUserName() {\n val user = currentUser\n if (user != null) {\n // ¡Smart cast funciona! user es un val local\n println(user.name)\n }\n}\nEste truco es el estándar de oro. Es simple, legible y no requiere bibliotecas adicionales. En 2025 sigue siendo la forma más recomendada.
\n\n2. Función let (una forma elegante)
\nLa función let es una excelente herramienta para trabajar con valores nullable. Ejecuta un bloque de código solo si el objeto no es null, y dentro del bloque el objeto está disponible como it (o se le puede asignar un nombre):