Tipos básicos de datos

En Kotlin, todo es un objeto en el sentido de que podemos llamar propiedades y métodos (funciones miembro) sobre cualquier variable. Algunos objetos tienen una representación interna especial y se suelen denominar valores primitivos. Esta entrada expone una introducción acerca de esos tipos básicos utilizados en Kotlin: números, caracteres, booleanos, arrays y strings, y sobre la inferencia de tipos y la conversión entre tipos. En entradas posteriores se profundizará en algunos de estos tipos y sus particularidades.


Para representar números enteros podemos utilizar Int, Long, Short y Byte, y para representar números decimales Float y Double. Algunos ejemplos de números:
var uno: Int = 1
val PI: Double = 3.1415
val pi: Float = 3.14f
// También es válido con F: val pi: Float = 3.14F
var dni: Long = 57195487L
// podemos utilizar guiones bajos para hacerlo más legible
var dni: Long = 57_195_487L
El tipo Char representa caracteres y se escribe entre comillas simples:
var c: Char = 'c'
var uno: Char = '1'
Se admiten algunas secuencias de escape como: \t, \b, \n, \r, \', \", \\ , \$.

Los booleanos admiten true y false y admiten operaciones de conjunción (&&), disyunción (||) y negación (!):
var verdad: Boolean = true
var falso: Boolean = false
var mentira: Boolean = verdad && falso
println(mentira)  // false
Un array es un contenedor que contiene datos (valores) de un mismo tipo. Para crear un array podemos usar la función arrayOf() y pasarle los valores de los elementos especificando el tipo de estos valores:
var numeros: Array = arrayOf(1, 2, 3)
var letras: Array = arrayOf('a', 'b', 'c')
Además, Kotlin tiene clases especializadas para crear arrays de tipos primitivos: ByteArray, ShortArray, IntArray, etc.
val x: IntArray = intArrayOf(1, 2, 3)
Accedemos a los elementos de un array a través de su índice:
var numeros: Array<Int> = arrayOf(1, 2, 3)    
println(numeros[0])  // 1
numeros[0] = 4
println(numeros[0])  // 4
numeros[3] = 4    // Error: índice fuera de los límites del array
También podemos iterar sobre un array. Un ejemplo:
var numeros: Array = arrayOf(1, 2, 3)   
numeros.forEach { print(it) }  // 123
En entradas posteriores trataremos con más detalle los arrays, mientras en el siguiente código vemos unos ejemplos de algunas maneras de crear arrays vacíos de distinto tipo:
fun main(args: Array<String>) {            
    
    val palabra = "KOTLIN"
    var arrayLetras = Array(palabra.length) { ' ' }
    for (i in arrayLetras.indices) {
        arrayLetras[i] = palabra[i]
        print("${arrayLetras[i]} ") // K O T L I N 
    }    
    println()
    
    val numeros = Array<Int>(3, { 0 })    
    for (i in numeros.indices) {
        numeros[i] = i + 1
        print("${numeros[i]} ") // 1 2 3
    }
    println() 
    
    val arrayString = Array(3) { "" }
    arrayString[0] = "A"
    arrayString[1] = "B"
    arrayString[2] = "C"
    arrayString.forEach { print("$it ") }  // A B C
    println()    
    
    val arrayEnteros = IntArray(10)    
    for (i in arrayEnteros.indices) {
        arrayEnteros[i] = i + 1
        print("${arrayEnteros[i]} ") // 1 2 3 4 5 6 7 8 9 10
    }
    println()    
    
    val arrayNulos = arrayOfNulls<Int>(10)
    for (i in 0 until arrayNulos.size) {
        arrayNulos[i] = i + 1
        print("${arrayNulos[i]} ") // 1 2 3 4 5 6 7 8 9 10
    }      
}
String hace referencia a un tipo de dato inmutable formado por una sucesión de caracteres a los que se accede por su índice:
var palabra = "kotlin"
println(palabra[2])  // t
Podemos concatenar Strings, incluso con otros tipos:
var palabra = "Kotlin"
var palabra2 = "Android"      
println(palabra + " & " + palabra2 + 2)  // Kotlin & Android2
Los Strings pueden contener expresiones que empiezan con el signo $ y que se evalúan cuando se encuentran entre llaves:
val i = 10
println("i = $i") // "i = 10"
val s = "abc"
println("$s.length is ${s.length}") // "abc.length is 3"

Comprobación de tipos

Podemos comprobar el tipo de dato de una variable con is:
var variable = 1
println("¿Variable es un número entero? " + (variable is Int))
println("¿Variable es un número entero? " + (variable !is Int))
println("¿Variable es un número entero? " + (variable !is String))  // ERROR: Incompatible types: String and Int
La primera expresión imprimirá true y la segunda false pero la tercera da un error ya que Kotlin es lo suficientemente poderoso como para determinar los tipos en el tiempo de compilación.

Podemos gestionarlo usando la instrucción when para verificar en un bucle for el tipo de cada elemento de una lista:
fun main(args: Array<String>) {                    
    val lista: List<Any> = listOf("kotlin", "java", 101, 12.5f,12.5456789,false)
    for(elemento in lista) {
        when (elemento) {
            is String -> println("String: $elemento")
            is Int -> println("Número entero: $elemento")
            is Double -> println("Número Double: $elemento")
            is Float -> println("Número Float: $elemento")
            else -> println("Tipo desconocido")
        }
    }          
}
Un ejemplo de una manera más eficiente de comprobar el tipo:
fun main(args: Array<String>) {                       
    fun getTipo(obj: Any?) {
        if (obj == null || obj !is String) {
            return
        }        
        println("Es un String")
    }

    getTipo(null)  // no devuelve nada
    getTipo(1) // no devuelve nada
    getTipo("kotlin") // Es un String              
}

Tipos inferidos

Kotlin es un lenguaje de tipo estático, es decir, el tipo de una variable se conoce durante el tiempo de compilación. No obstante, como se ha visto, en muchas ocasiones no es necesario especificar el tipo de datos con el que estamos trabajando, siempre que el compilador lo pueda inferir.
var x = 7      // Int
var y = 5
var z = x + y    // Int
var h = "Hola"  // String

Conversión de tipos

Los números admiten las siguientes conversiones explícitas: toByte(), toShort(), toInt(), toLong(), toFloat(), toDouble(), toChar(). Por ejemplo:
val b: Byte = 1
val i: Int = b.toInt()
Otros ejemplos de conversiones explícitas:
var uno: String = "1"          
var numero1: Int = uno.toInt()
var one: String = numero1.toString()
También podemos hacer conversiones explícitas usando el operados as:
val objeto1: Any = "Hello World"
val str: String = objeto1 as String
println(str.length) // 11

val objeto2: Any = 2
val num: Int = objeto2 as Int
println(num * num) // 4
Además pueden producirse conversiones implícitas, como por ejemplo:
val l = 1L + 3     // Long + Int => Long
En las conversiones implícitas, hay que tener en cuenta que los tipos numéricos más simples no se pueden asignar a otros más complejos (por ejemplo, un entero no puede ser asignado a una variable de un long) y en esos casos hay que utilizar una conversión explícita.

Comentarios

Entradas populares

I/O: entrada y salida de datos en consola

Recursos gratis para aprender Kotlin

Lectura y escritura de archivos