Capacitación de Kotlin para programadores 2: conceptos básicos de Kotlin

Este codelab es parte del curso Capacitación de Kotlin para programadores. Aprovecharás al máximo este curso si trabajas con los codelabs en secuencia. Según tus conocimientos, es posible que puedas cambiar algunas secciones. Este curso está dirigido a los programadores que conocen un lenguaje orientado a objetos y desean aprender Kotlin.

Introducción

En este codelab, aprenderás los conceptos básicos del lenguaje de programación Kotlin: tipos de datos, operadores, variables, estructuras de control y variables anulables frente a variables que no admiten nulidades. Este curso está dirigido a los programadores que conocen un lenguaje orientado a objetos y desean aprender Kotlin.

En lugar de compilar una sola app de muestra, las lecciones de este curso están diseñadas para aumentar tu conocimiento, pero son semiindependientes entre sí a fin de que puedas leer las secciones con las que estás familiarizado. Para vincularlos, muchos de los ejemplos usan un tema de acuario. Si deseas ver la historia completa del acuario, consulta el curso de Udacity Capacitación de Kotlin para programadores.

Conocimientos que ya deberías tener

  • Cómo crear un proyecto en IntelliJ IDEA
  • Cómo abrir y ejecutar código en REPL (Kotlin-Eval-Print Loop) de Kotlin en IntelliJ IDEA (Herramientas > Kotlin > Kotlin REPL)

Qué aprenderás

  • Cómo usar tipos de datos, operadores y variables de Kotlin
  • Cómo trabajar con booleanos y condiciones
  • La diferencia entre las variables anulables y no anulables
  • Cómo funcionan los arrays, las listas y los bucles en Kotlin

Actividades

  • Cómo trabajar con REPL de Kotlin para aprender los conceptos básicos de Kotlin

En esta tarea, aprenderás sobre operadores y tipos en el lenguaje de programación Kotlin.

Paso 1: Explora los operadores numéricos

  1. Abre IntelliJ IDEA si aún no está abierta.
  2. Para abrir REPL de Kotlin, selecciona Tools > Kotlin > Kotlin REPL.

Al igual que con otros lenguajes, Kotlin utiliza +, -, * y / para los signos más, menos, tiempos y división. Kotlin también admite diferentes tipos de número, como Int, Long, Double y Float.

  1. Ingresa las siguientes expresiones en REPL. Para ver el resultado, presiona Control+Enter (Command+Enter en una Mac) después de cada uno.
1+1
⇒ res8: kotlin.Int = 2

53-3
⇒ res9: kotlin.Int = 50

50/10
⇒ res10: kotlin.Int = 5

1.0/2.0
⇒ res11: kotlin.Double = 0.5

2.0*3.5
⇒ res12: kotlin.Double = 7.0

Tenga en cuenta que los resultados de las operaciones mantienen los tipos de los operandos, por lo que 1/2 = 0, pero 1.0/2.0 = 0.5.

  1. Prueba algunas expresiones con diferentes combinaciones de números enteros y decimales.
6*50
⇒ res13: kotlin.Int = 300

6.0*50.0
⇒ res14: kotlin.Double = 300.0

6.0*50
⇒ res15: kotlin.Double = 300.0
  1. Llama a algunos métodos de los números. Kotlin conserva los números como primitivas, pero te permite llamar a métodos en números como si fueran objetos.
2.times(3)
⇒ res5: kotlin.Int = 6

3.5.plus(4)
⇒ res8: kotlin.Double = 7.5

2.4.div(2)
⇒ res9: kotlin.Double = 1.2

Paso 2: Practica con los tipos

Kotlin no realiza una conversión implícita entre los tipos de números, por lo que no puedes asignar un valor corto directamente a una variable larga ni un Byte a un Int. Esto se debe a que la conversión de números implícito es una fuente común de errores en los programas. Siempre puedes asignar valores de diferentes tipos mediante la transmisión.

  1. Para ver algunas de las conversiones posibles, define una variable de tipo Int en REPL.
val i: Int = 6
  1. Crea una nueva variable y, luego, ingresa el nombre de la variable que se muestra arriba seguido de .to.
val b1 = i.to

IntelliJ IDEA muestra una lista de finalizaciones posibles. Este autocompletado funciona para variables y objetos de cualquier tipo.

  1. Selecciona toByte() de la lista y, luego, imprime la variable.
val b1 = i.toByte()
println(b1)
⇒ 6
  1. Asigna un valor Byte a variables de diferentes tipos.
val b2: Byte = 1 // OK, literals are checked statically
println(b2)
⇒ 1

val i1: Int = b2
⇒ error: type mismatch: inferred type is Byte but Int was expected

val i2: String = b2
⇒ error: type mismatch: inferred type is Byte but String was expected

val i3: Double = b2
⇒ error: type mismatch: inferred type is Byte but Double was expected
  1. Para las tareas que mostraron errores, intenta transmitirlas.
val i4: Int = b2.toInt() // OK!
println(i4)
⇒ 1

val i5: String = b2.toString()
println(i5)
⇒ 1

val i6: Double = b2.toDouble()
println(i6)
⇒ 1.0
  1. Para que las constantes numéricas largas sean más legibles, Kotlin te permite colocar guiones bajos en los números, donde te resulte más conveniente. Intenta ingresar diferentes constantes numéricas.
val oneMillion = 1_000_000
val socialSecurityNumber = 999_99_9999L
val hexBytes = 0xFF_EC_DE_5E
val bytes = 0b11010010_01101001_10010100_10010010

Paso 3: Conozca el valor de los tipos de variables

Kotlin admite dos tipos de variables: modificables y no modificables. Con val, puedes asignar un valor una vez. Si intentas asignar algo nuevamente, se mostrará un error. Con var, puedes asignar un valor y, luego, cambiar el valor más adelante en el programa.

  1. Define las variables con val y var y, luego, asígnales valores nuevos.
var fish = 1
fish = 2
val aquarium = 1
aquarium = 2
⇒ error: val cannot be reassigned

Puedes asignar un valor a fish y, luego, un valor nuevo, ya que se define con var. Si intentas asignar un valor nuevo a aquarium, se mostrará un error porque se define con val.

El tipo que almacenas en una variable se infiere cuando el compilador puede determinarlo desde el contexto. Si lo deseas, siempre puedes especificar el tipo de una variable de manera explícita mediante la notación de dos puntos.

  1. Defina algunas variables y especifique el tipo de forma explícita.
var fish: Int = 12
var lakes: Double = 2.5

Una vez que tú o el compilador hayan asignado un tipo, no podrás cambiar el tipo o recibirás un error.

Paso 4: Obtén más información sobre las strings

Las strings en Kotlin funcionan de forma muy similar a las de cualquier otro lenguaje de programación, con " para strings y ' para caracteres individuales, y puedes concatenar strings con el operador +. Puedes crear plantillas de strings combinándolas con valores; el nombre $variable se reemplaza por el texto que representa el valor. Esto se denomina interpolación variable.

  1. Crea una plantilla de strings.
val numberOfFish = 5
val numberOfPlants = 12
"I have $numberOfFish fish" + " and $numberOfPlants plants"
⇒ res20: kotlin.String = I have 5 fish and 12 plants
  1. Crea una plantilla de strings con una expresión. Al igual que en otros lenguajes, el valor puede ser el resultado de una expresión. Usa llaves {} para definir la expresión.
"I have ${numberOfFish + numberOfPlants} fish and plants"
⇒ res21: kotlin.String = I have 17 fish and plants

En esta tarea, aprenderás sobre valores booleanos y las condiciones de verificación en el lenguaje de programación Kotlin. Al igual que otros lenguajes, Kotlin tiene operadores booleanos y operadores booleanos, como "menor, igual que, mayor que" y así sucesivamente (<, ==, >, !=, <= y >=).

  1. Escribe una sentencia if/else.
val numberOfFish = 50
val numberOfPlants = 23
if (numberOfFish > numberOfPlants) {
    println("Good ratio!") 
} else {
    println("Unhealthy ratio")
}
⇒ Good ratio!
  1. Prueba un rango en una sentencia if. En Kotlin, la condición que pruebes también puede usar rangos.
val fish = 50
if (fish in 1..100) {
    println(fish)
}
⇒ 50
  1. Escribe una if con varios casos. En condiciones más complicadas, usa && lógico y ||. Al igual que en otros idiomas, puedes tener varios casos si usas else if.
if (numberOfFish == 0) {
    println("Empty tank")
} else if (numberOfFish < 40) {
    println("Got fish!")
} else {
    println("That's a lot of fish!")
}
⇒ That's a lot of fish!
  1. Prueba una sentencia when. Hay una forma más ingeniosa de escribir esa serie de sentencias if/else if/else en Kotlin, con la sentencia when, que es similar a la sentencia switch en otros lenguajes. Las condiciones en una declaración when también pueden usar rangos.
when (numberOfFish) {
    0  -> println("Empty tank")
    in 1..39 -> println("Got fish!")
    else -> println("That's a lot of fish!")
}
⇒ That's a lot of fish!

En esta tarea, aprenderás sobre las variables anulables y no anulables. Los errores de programación relacionados con los valores nulos fueron la fuente de innumerables errores. Kotlin busca reducir los errores mediante la introducción de variables que no admiten valores nulos.

Paso 1: Obtén información sobre la nulabilidad

De forma predeterminada, las variables no pueden ser null.

  1. Declara un Int y asígnale null.
var rocks: Int = null
⇒ error: null can not be a value of a non-null type Int
  1. Usa el operador de signo de interrogación, ?, después del tipo para indicar que una variable puede ser nula. Declara un Int? y asígnale null.
var marbles: Int? = null

Cuando tienes tipos de datos complejos, como una lista:

  • Puedes permitir que los elementos de la lista sean nulos.
  • Puedes permitir que la lista sea nula, pero si no es nula, sus elementos no pueden ser nulos.
  • Puedes permitir que la lista o los elementos sean nulos.

En una tarea posterior, se analizarán las listas y otros tipos de datos complejos.

Paso 2: Obtén información sobre ? y ?: operadores

Puedes probar null con el operador ?, lo que te ahorra el trabajo de escribir muchas declaraciones if/else.

  1. Escribe algún código para verificar si la variable fishFoodTreats no es null. Luego, disminuya esa variable.
var fishFoodTreats = 6
if (fishFoodTreats != null) {
    fishFoodTreats = fishFoodTreats.dec()
}
  1. Ahora, observa la forma de escribir en Kotlin con el operador ?.
var fishFoodTreats = 6
fishFoodTreats = fishFoodTreats?.dec()
  1. También puedes encadenar pruebas nulas con el operador ?:. Observa este ejemplo:
fishFoodTreats = fishFoodTreats?.dec() ?: 0

Es una abreviatura de &sit; si fishFoodTreats no es null, reduce y úsalo. De lo contrario, usa el valor después de ?:, que es 0. Si fishFoodTreats es null, se detiene la evaluación y no se llama al método dec().

Un punto sobre los punteros nulos

Si realmente te gusta NullPointerExceptions, Kotlin te permite conservarlas. El operador de aserción no nulo, !! (doble salto), convierte cualquier valor en un tipo no nulo y arroja una excepción si el valor es null.

val len = s!!.length   // throws NullPointerException if s is null

En esta tarea, aprenderás sobre arrays y listas, y aprenderás diferentes maneras de crear bucles en el lenguaje de programación Kotlin.

Paso 1: Haz listas

Las listas son un tipo fundamental en Kotlin y son similares a las listas en otros lenguajes.

  1. Declara una lista con listOf y, luego, imprímela. No se puede cambiar esta lista.
val school = listOf("mackerel", "trout", "halibut")
println(school)
⇒ [mackerel, trout, halibut]
  1. Declara una lista que se pueda cambiar con mutableListOf. Quita un elemento.
val myList = mutableListOf("tuna", "salmon", "shark")
myList.remove("shark")
⇒ res36: kotlin.Boolean = true

El método remove() muestra true cuando se quita correctamente el elemento que se pasó.

Paso 2: Crea arreglos

Al igual que otros lenguajes, Kotlin tiene arreglos. A diferencia de las listas de Kotlin, que tienen versiones inmutables y mutables, no hay una versión mutable de Array. Una vez que creas un arreglo, el tamaño es fijo. No es posible agregar ni quitar elementos, excepto si se copia a un arreglo nuevo.

Las reglas para usar val y var son las mismas con los arreglos y las listas.

  1. Declara un arreglo de strings con arrayOf. Usa la utilidad de arreglo java.util.Arrays.toString() para imprimirla.
val school = arrayOf("shark", "salmon", "minnow")
println(java.util.Arrays.toString(school))
⇒ [shark, salmon, minnow]
  1. Un arreglo declarado con arrayOf no tiene un tipo asociado con los elementos, por lo que puedes mezclar tipos, lo que es útil. Declara un arreglo con diferentes tipos.
val mix = arrayOf("fish", 2)
  1. También puedes declarar arreglos con un tipo para todos los elementos. Declara un arreglo de números enteros con intArrayOf(). Existen compiladores o funciones de instancia correspondientes para arreglos de otros tipos.
val numbers = intArrayOf(1,2,3)
  1. Combina dos arreglos con el operador +.
val numbers = intArrayOf(1,2,3)
val numbers3 = intArrayOf(4,5,6)
val foo2 = numbers3 + numbers
println(foo2[5])
=> 3
  1. Prueba diferentes combinaciones de arreglos y listas anidados. Al igual que en otros lenguajes, puedes anidar arrays y listas. Es decir, cuando colocas un arreglo en uno, tienes un arreglo de arreglos, no uno compactado de los contenidos de los dos. Los elementos de un arreglo también pueden ser listas, y los elementos de las listas pueden ser arreglos.
val numbers = intArrayOf(1, 2, 3)
val oceans = listOf("Atlantic", "Pacific")
val oddList = listOf(numbers, oceans, "salmon")
println(oddList)
⇒ [[I@89178b4, [Atlantic, Pacific], salmon]

El primer elemento, numbers, es un Array. Cuando no usas la utilidad de arreglo para imprimirla, Kotlin imprime la dirección en lugar del contenido del arreglo.

  1. Una buena función de Kotlin es que puedes inicializar arreglos con código en lugar de inicializarlos en 0. Prueba este ejemplo:
val array = Array (5) { it * 2 }
println(java.util.Arrays.toString(array))
⇒ [0, 2, 4, 6, 8]

El código de inicialización se encuentra entre las llaves, {}. En el código, it hace referencia al índice del array que comienza con 0.

Paso 3: Crea bucles

Ahora que tienes listas y arreglos, la ejecución de bucles por los elementos funciona como se espera.

  1. Crea un array. Usa un bucle for para iterar a través del arreglo e imprimir los elementos.
val school = arrayOf("shark", "salmon", "minnow")
for (element in school) {
    print(element + " ")
}
⇒ shark salmon minnow
  1. En Kotlin, puedes realizar un bucle a través de los elementos y los índices al mismo tiempo. Prueba este ejemplo:
for ((index, element) in school.withIndex()) {
    println("Item at $index is $element\n")
}
⇒ Item at 0 is shark
Item at 1 is salmon
Item at 2 is minnow
  1. Prueba diferentes tamaños y rangos de pasos. Puedes especificar alfabéticamente rangos de números o de caracteres. Y, como en otros idiomas, no es necesario avanzar un paso por otro. Puedes retroceder con downTo.
for (i in 1..5) print(i)
⇒ 12345

for (i in 5 downTo 1) print(i)
⇒ 54321

for (i in 3..6 step 2) print(i)
⇒ 35

for (i in 'd'..'g') print (i)
⇒ defg
  1. Prueba con algunos bucles. Al igual que otros lenguajes, Kotlin tiene bucles while, bucles do...while y operadores ++ y --. Kotlin también tiene bucles repeat.
var bubbles = 0
while (bubbles < 50) {
    bubbles++
}
println("$bubbles bubbles in the water\n")

do {
    bubbles--
} while (bubbles > 50)
println("$bubbles bubbles in the water\n")

repeat(2) {
     println("A fish is swimming")
}
⇒ 50 bubbles in the water
49 bubbles in the water
A fish is swimmingA fish is swimming

Kotlin es muy similar a otros lenguajes cuando se trata de conceptos básicos como operadores, listas y bucles, pero existen algunas diferencias importantes.

Es posible que las siguientes funciones sean diferentes en Kotlin de las que conoces en otros idiomas:

  • Los tipos de Kotlin no se pueden convertir de manera implícita. Usa la transmisión.
  • Las variables declaradas con val solo se pueden asignar una vez.
  • Las variables de Kotlin no son nulas de forma predeterminada. Usa ? para anular las variables.
  • Con Kotlin, puedes aplicar un bucle al índice y a los elementos de un array al mismo tiempo en un bucle for.

Las siguientes construcciones de programación de Kotlin son similares a las de otros lenguajes:

  • Los arrays y las listas pueden tener un solo tipo o varios.
  • Se pueden anidar los arrays y las listas.
  • Puedes crear bucles con for, while, do/while y repeat.
  • La sentencia when es la versión de Kotlin de la declaración switch, pero when es más flexible.

Documentación de Kotlin

Si necesitas más información sobre algún tema de este curso o si no puedes avanzar, https://kotlinlang.org es tu mejor punto de partida.

Instructivos de Kotlin

El sitio web https://try.kotlinlang.org incluye instructivos enriquecidos llamados Kotlin Koans, un intérprete basado en la Web, y un conjunto completo de documentación de referencia con ejemplos.

Curso de Udacity

Para ver el curso de Udacity sobre este tema, consulta el Capacitación de Kotlin para programadores.

IntelliJ IDEA

Puedes encontrar la documentación de IntelliJ IDEA en el sitio web de JetBrains.

En esta sección, se enumeran las posibles tareas para los alumnos que trabajan con este codelab como parte de un curso que dicta un instructor. Depende del instructor hacer lo siguiente:

  • Si es necesario, asigna la tarea.
  • Informa a los alumnos cómo enviar los deberes.
  • Califica las tareas.

Los instructores pueden usar estas sugerencias lo poco o lo que quieran, y deben asignar cualquier otra tarea que consideren apropiada.

Si estás trabajando en este codelab por tu cuenta, usa estas tareas para poner a prueba tus conocimientos.

Responde estas preguntas

Pregunta 1

¿Cuál de las siguientes afirmaciones declara una lista inmutable de strings?

val school = arrayOf("shark", "salmon", "minnow")

var school = arrayOf("shark", "salmon", "minnow")

val school = listOf("shark", "salmon", "minnow")

val school = mutableListOf("shark", "salmon", "minnow")

Pregunta 2

¿Cuál será el resultado del siguiente código?
for (i in 3..8 step 2) print(i)

▢ 345678

▢ 468

▢ 38

▢ 357

Pregunta 3

¿Cuál es el propósito del signo de interrogación en este código?
var rocks: Int? = 3

▢ No se corrigió el tipo de la variable rocks.

▢ La variable rocks se puede establecer como nula.

▢ La variable rocks no se puede establecer como nula.

▢ La variable rocks no debe inicializarse de inmediato.

Continúa con la siguiente lección: 3. Funciones

Para obtener una descripción general del curso, incluidos vínculos a otros codelabs, consulta "Capacitación de Kotlin para programadores: Bienvenido al curso."