Comprobación y conversión de tipos con is y as



Cuando vimos los tipos básicos de datos, ya adelantamos algunas cuestiones básicas sobre la comprobación y conversión de tipos en Kotlin, y ahora vamos a recordarlas y profundizar en ellas.

Con el operador is (y con su negación !is) podemos verificar si un objeto se ajusta a un determinado tipo (en el siguiente ejemplo, utilizando el supertipo Any estamos diciendo que puede ser de cualquier tipo no anulable):
val obj1: Any = "¿Soy un String?"
if (obj1 is String) {
    println(obj1.length)
}

val obj2: Any = 2
if (obj2 !is String) { // if !(obj2 is String)
    println("No es un String")
} else {
    println(obj2.length)
}
Es posible que hayas pasado por alto que en el ejemplo anterior se ha producido una conversión implícita de tipos, y es que en ocasiones en Kotlin no es necesario usar operadores de conversión explícitos porque el compilador realiza un seguimiento y comprobación de los tipos y automáticamente inserta de manera segura las conversiones cuando son necesarias (cuando tiene la garantía de que la variable no puede cambiar entre la verificación y su uso posterior). Más claro en otro ejemplo donde el parámetro de la función pasa automáticamente a convertirse en un String si el argumento que invoca la función es un String:
fun checkTipo(x: Any) {
    if (x is String) { // conversión implícita
        println(x.length) 
    }
}
El compilador es lo suficientemente inteligente como para saber que una conversión es segura si una comprobación negativa conduce a un return o si aparece en el lado derecho de && y ||:
if (x !is String) return
print(x.length) // conversión automática a String

// conversión automática a String
if (x !is String || x.length == 0) return

// conversión automática a String
if (x is String && x.length > 0) {
    print(x.length)
}
Estas conversiones inteligentes funcionan también en expresiones when y bucles while:
when (x) {
    is Int -> print(x + 1)
    is String -> print(x.length + 1)
    is IntArray -> print(x.sum())
}
Cuando la conversión no es posible, el operador de conversión lanza una excepción, y entonces se le conoce como operador de conversión inseguro y es realizado por el operador intercalado as:
val x: String = y as String
Hay que tener en cuenta que null no se puede convertir a String ya que este tipo es no anulable (ver Gestión de tipos nulos en Kotlin); es decir, si en el ejemplo anterior y es nulo, se genera una excepción y habría que tener un tipo anulable después del operador as:
val x: String? = y as String?
Para evitar que se lance una excepción, se puede usar el operador de conversión as? que devuelve nulo en caso de fallo (ten en cuenta que a pesar de que después de as? hay un String no anulable, el resultado de la conversión con as? es anulable):
val x: String? = y as? String

Comentarios

Entradas populares

I/O: entrada y salida de datos en consola

Recursos gratis para aprender Kotlin

Lectura y escritura de archivos