Vamos a ver una colección de modismos que se utilizan con frecuencia.
//sampleStart data class Persona(var nombre: String, var email: String) //sampleEnd fun main() { val persona = Persona("Pepe", "pepe@email.com") println("El nombre es ${persona.nombre}") persona.email= "jose@gmail.com" println("El nuevo email es ${persona.email}") }
Con esa sola línea obtendríamos:
var
) de todas las propiedadesequals()
hashCode()
toString()
copy()
component1()
, component2()
, …, para todas las propiedades (Ver Clases de Datos)//sampleStart fun ejemplo(numero: Int = 0, texto: String = "Vacio") = println("El numero es $numero y el texto es $texto") //sampleEnd fun main() { ejemplo() ejemplo(100,"hola") }
fun main() { //sampleStart val lista = listOf(-2,-1,0,1,2,3) println("Lista sin filtrar: $lista") val numerosPositivos = lista.filter { x -> x > 0 } println("Lista filtrada: $numerosPositivos") //sampleEnd }
O una alternativa incluso más corta utilizando it
:
fun main() { val lista = listOf(-2,-1,0,1,2,3) println("Lista sin filtrar: $lista") //sampleStart val numerosPositivos= lista.filter { it > 0 } //sampleEnd println("Lista filtrada: $numerosPositivos") }
fun main() { //sampleStart val nombre = "Javier" println("Su nombre es $nombre") // "Su nombre es Javier" //sampleEnd }
class Persona(val nombre: String) class Coche(val marca: String) val persona = Persona("Juan") val coche = Coche("SEAT") //sampleStart fun controlInstancia(parametro: Any) { when (parametro) { is Persona -> println("Es una persona cuyo nombre es ${parametro.nombre}") is Coche -> println("Es un coche de la marca ${parametro.marca}") else -> println("Desconocido") } } //sampleEnd fun main() { controlInstancia(persona) // "Es una persona" controlInstancia(coche) // "Es un coche" controlInstancia("hola") // "Desconocido" }
fun main() { //sampleStart val mapaPersonaCoche = mapOf("Juan" to "SEAT", "Pedro" to "Opel") for ((k, v) in mapaPersonaCoche) { println("$k -> $v") } //sampleEnd }
Alternativamente también podríamos hacerlo así:
fun main() { //sampleStart val mapaPersonaCoche = mapOf("Juan" to "SEAT", "Pedro" to "Opel") for (map in mapaPersonaCoche) { println("${map.key} -> ${map.value}") } //sampleEnd }
fun main() { //sampleStart val lista = mutableListOf<Int>() for (i in 1..10) lista.add(i) println(lista).also { lista.clear() } for (i in 1 until 20) lista.add(i) println(lista).also { lista.clear() } for (x in 2..10 step 2) lista.add(x) println(lista).also { lista.clear() } for (x in 10 downTo 1) lista.add(x) println(lista).also { lista.clear() } val x = 3 if (x in 1..10) print("Está en el intervalo") // Evita anidar 'if/for' colocando el intervalo en el 'if' //sampleEnd }
Como puedes ver, he utilizado .also
para que una vez que se haya mostrado la lista se limpie a posteriori. Observa también que aunque la lista es val
, es decir, no podrás hacer lista = otraList
pero si podrás modificar sus parámetros ya que es una MutableList
.
fun main() { //sampleStart val lista = listOf("a", "b", "c") val listaMutable = mutableListOf("a", "b", "c").apply { add("d") remove("b") } //sampleEnd println(lista) println(listaMutable) }
Con .apply
podemos utilizar varias funciones sobre el mismo objeto sin tener que escribirlo con cada función. Es muy útil cuando ya que además de ahorrarte código duplicado facilita su lectura.
fun main() { //sampleStart val mapa = mapOf("a" to 1, "b" to 2, "c" to 3) //sampleEnd println(mapa) }
Como hemos dicho antes, en Kotlin puedes utilizar las variantes mutables de ciertas interfaces. Como ejemplo, las listas o los mapas tienen su variante mutable,
fun main() { //sampleStart val mapa = mutableMapOf("a" to 1, "b" to 2, "c" to 3) println(mapa["a"]) // "1" mapa["a"] = 10 // Utilizamos mutableMapOf para poder modificar el valor println(mapa["a"]) // "10" //sampleEnd }
Como puedes ver, aunque utilizamos val
podemos modificar los valores de cada clave. Si añadiésemos un nuevo valor también funcionaría:
fun main() { val mapa = mutableMapOf("a" to 1, "b" to 2, "c" to 3) //sampleStart mapa["e"] = 4 println(mapa["e"]) // "4" //sampleEnd }
Sin embargo si tratásemos de igualar mapa a otro mapa diferente, no podríamos compilar:
fun main() { //sampleStart val map = mapOf("a" to 1) val otroMap= mutableMapOf("b" to 2) map = otroMap //sampleEnd }
Cuando utilizas by lazy
lo que haces es que la variable no se inicie en el momento en el que la declaras. Se inicia en el momento en el que se usa.
//sampleStart val texto: String by lazy { "lazy property!" } //sampleEnd fun main() { println(texto) // Ahora se inicia la variable 'texto' }
Esta es una de las características que más me gustan de Kotlin. Puedes añadir comportamientos o funcionalidades nuevas a cualquier clase. Por ejemplo vamos a añadir a String
una función que invierta la cadena de texto que le pasemos.
//sampleStart fun String.invertirTexto(): String { var textoInvertido = "" for (i in (this.length - 1 downTo 0)) { textoInvertido = textoInvertido + this.get(i) } return textoInvertido } //sampleEnd fun main() { val texto = "aniram al ne etatsíla" println(texto.invertirTexto()) // Mostraría 'Alístate en la marina' }
Un ejemplo de esto aplicado a Android sería crear una función para añadir una nueva funcionalidad a un ImageView
: Descargar imágenes de Internet con Picasso o Glide.
fun ImageView.loadUrl(url: String) { Picasso.with(context).load(url).into(this) } imageView.loadUrl(url) // Bye bye boilerplate!
He creado un repositorio en GitHub con una recopilación de estas funciones. Puedes sugerirme más mediante pull requests/issues o dejando un comentario en esta entrada para añadir más.
//sampleStart object Recurso { val nombre = "Juan" } //sampleEnd fun main() { println(Recurso.nombre) // "Juan" }
También es posible crear un objeto anónimo:
fun main() { //sampleStart val recurso = object { val nombre = "Pepe" } //sampleEnd println(recurso.nombre) // "Pepe" }
Imagina que tratas de obtener una lista de objetos de una API, y por algún motivo no puede obtener la lista, obteniendo una lista null
, para evitar un error simplemente utilizaríamos ?
de esta forma:
fun main() { //sampleStart val listaNull: List<String>? = null // Simulamos obtener una lista vacia println(listaNull?.size) // Compilaría y mostraría 'null' //sampleEnd }
También conocido como Elvis operator por su forma ?:
fun main() { //sampleStart val listaNull: List<String>? = null println(listaNull?.size ?: "Lista vacia") // "Lista vacia" //sampleEnd }
fun main() { //sampleStart val listaNull: List<String> = listOf() println(listaNull.firstOrNull()) // "null" //sampleEnd }
En el siguiente caso como la lista será nula, no imprimirá el texto, pero tampoco obtendremos una excepción. Esto es realmente útil en Android ya que muchas veces tenemos ciertos elementos que nunca sabemos si son nulos o no como el contexto en un fragmento. Con un símbolo de interrogación evitamos tener que colocar el clásico if (elemento != null) ...
fun main() { //sampleStart val listaNull: List<String>? = null listaNull?.let { println("La lista está vacía") } //sampleEnd }
//sampleStart fun obtenerColorPorID(color: Int): String { return when (color) { 0 -> "Rojo" 1 -> "Verde" 2 -> "Azul" else -> "Desconocido" } } //sampleEnd fun main() { val color = obtenerColorPorID(1) println(color) // "Verde" }
//sampleStart fun mostrarCoche() { val coche = try { "SEAT" } catch (e: ArithmeticException) { throw IllegalStateException(e) } println(coche) } //sampleEnd fun main() { mostrarCoche() // Si no hay ningún error mostraría "SEAT" }
//sampleStart fun obtenerColorPorID(marca: Int) { val color = if (marca == 1) "Rojo" else "Verde" println(color) } //sampleEnd fun main() { obtenerColorPorID(1) // "Rojo" }
//sampleStart fun rellenarDeAes(tamaño: Int): CharArray { return CharArray(tamaño).apply { fill('A') } } //sampleEnd fun main() { val charArrayAes = rellenarDeAes(4) for (i in 0 until charArrayAes.size) print("(${i + 1}, ${charArrayAes[i]}) ") }
La siguiente función:
//sampleStart fun nombre() = "Juan" //sampleEnd fun main() { println(nombre()) // "Juan" }
Es equivalente a:
//sampleStart fun nombre(): String { return "Juan" } //sampleEnd fun main() { println(nombre()) // "Juan" }
Estas funciones pueden ser combinadas con otros modismos, por ejemplo con un when
//sampleStart fun obtenerColorPorID(color: Int): String = when (color) { 0 -> "Rojo" 1 -> "Verde" 2 -> "Azul" else -> "Desconocido" } //sampleEnd fun main() { println(obtenerColorPorID(2)) // "Azul" }
Para evitar tener que escribir varias veces el mismo código y evitar duplicados, puedes utilizar todos los métodos de un objeto gracias a with
:
class Coches { fun seat() = "SEAT" fun opel() = "OPEL" fun bmw() = "BMW" } fun main() { val coches = Coches() //sampleStart with(coches) { val listaDeCoches = listOf(seat(), opel(), bmw()) println(listaDeCoches) } //sampleEnd }
En esta lección aprenderás a declarar variables y los tipos básicos.
La mejor forma de aprender algo en esta vida es a base de practicar. Espero…
La principal forma de iniciar una corrutina en Kotlin es con el coroutine builder launch…
Las coroutines en Kotlin vienen a tratar de solucionar todos los problemas y dificultades que…
Con este esquema te puedes guiar a la hora de elegir el modismo o función…
El último que queda por ver es with qué en inglés significa "con". Por lo…