Tema 1. Kotlin Básico
VERSIÓN ACTUAL
En el momento de escribir ésta guía la versión más reciente de Kotlin era 1.8.0 RC.
FUNCIÓN MAIN()
Igual que en otros lenguajes clásicos como C, el punto de entrada del programa en Kotlin es la función Main(). Esto significa que solo se ejecutará aquello que se encuentre dentro de dicha función.
COMENTARIOS
Dado un bloque de código, a veces puede ser útil explicar qué hace o en qué consiste, o bien hacer que una línea no se ejecute por algún motivo, pero que siga presente en dicho código. Aquí entran en juego los comentarios, que son parte del código, pero no se ejecutan.
En Kotlin, se pueden diferenciar dos tipos de comentarios:
Linea de comentarios
En este caso, el comentario solo ocupa desde su inicio hasta el salto de linea. Se representa con "//
"
Comentario multilínea
Existe la opción de que el comentario ocupe varias líneas. En este caso utilizamos "/*
" para abrir el comentario y "*/
" para cerrarlo.
PAQUETES E IMPORTACIONES
Paquetes
La declaración de paquetes va en el inicio de un archivo fuente usando la sentencia package
y luego el nombre del paquete al que pertenecerá el archivo.
El hecho de declarar un paquete al inicio del archivo nos permite importar todas las funciones y clases de dicho archivo en otros importando dicho paquete.
En este caso, la función suma() tendría como nombre completo: prueba.test.suma()
.
Lo mismo ocurriría con la clase ejemplo: prueba.test.Ejemplo
.
Importaciones
Utilizando la directiva import
podemos importar los paquetes que queramos a nuestro código fuente para así utilizar las funciones, clases y constantes de dicho paquete en nuestro código.
Siguiendo con el ejemplo:
Se pueden importar:
Clases
Funciones y propiedad de alto nivel.
Funciones y propiedades en declaración de objetos.
Enumeraciones de constantes.
Además, puedes importar de diferentes maneras:
Si las declaraciones de alto nivel están marcadas como private
, en ese caso, solo pueden utilizarse en el archivo en el que se han declarado.
NULL SAFETY
Kotlin se desarrolló en parte para evitar que pudieran existir las (odiadas) excepciones de "Null Pointer Exception".
Sin embargo, existe la posibilidad de que un puntero nulo suponga un fallo de seguridad en la arquitectura del programa. Es por eso que se desarrollaron los operadores ?
y !!
.
Las únicas maneras de que en Kotlin nos encontremos con una NPE son:
Llamada explicita a
throw NullPointerException()
.Utilización del operador
!!
.Inconsistencias en inicializaciones (avanzado):
Un
this
sin inicializar disponible en un constructor utilizado en el código (leaking this).El constructor de una superclase llama a un miembro cuya implementación en la clase derivada utiliza un estado no inicializado.
Interoperabilidad con Java.
Operador ?
Este operador se utiliza a la hora de Castear (dar un tipo) una variable y nos permite que el tipo pueda ser también nulo.
Operador !!
Con este operador, nosotros le estamos asegurando al compilador que una variable no va a ser nula.
Cuando se utiliza dicho operador y la variable es nula, salta la excepción NPE permitiéndonos tratarla y evitando un problema de seguridad peor.
Operador Elvis
Por último tenemos el operador Elvis. Este operador nos permite ejecutar una expresión si la variable es nula, mientras que si es no nula, utilizará la referencia de dicha variable.
Se llama operador Elvis por que se parece al cantante de country Elvis Presley "?:
"
El operador Elvis evaluará la expresión del lado derecho solo si la expresión de la izquierda es nula.
Si tenemos el siguiente código:
Podemos simplificar los bloques if, else
si utilizamos el operador elvis
:
El operador Elvis es la espina dorsal de la seguridad ante nulos ya que facilita la capacidad de realizar comprobaciones y ofrece código alternativo en el caso de que la variable tenga un valor nulo.
STANDARD INPUT / OUTPUT
Standard I/O es la forma en la que nos referimos a mostrar información por consola (standard Output) y a recibir datos desde la consola (standard input).
Standard Output
En Kotlin existen dos funciones básicas para mostrar información por consola:
Obviamente, Standard Output recibe datos de tipo String aunque si le pasamos otro tipo de datos lo convertirá a String por sí solo.
Standard Input
Hay tres opciones para recibir input en Kotlin:
readline()!!
Es la primera función para Standard Input que se implementó en Kotlin y tiene problemas con los valores nulos. Es por eso que se acompaña siempre del operador !!
readln()
Desde Kotlin 1.6.0 se aplicó la funcionalidad de readLine()!!
a la función readln()
. Es por eso que es preferible utilizar esta opción ya que es más moderna.
Scanner
En el caso de que quiera introducir datos que no sean del tipo String, puede utilizar la clase de Java Scanner. Para ello hay que seguir los siguientes pasos:
Importar Scanner.
Generar un objeto Scanner.
Comenzar a recibir datos.
Scanner es una forma más potente de recibir Input pero también es más costosa a nivel de recursos.
Por otro lado, aunque uno reciba los datos del tipo String con readln(), siempre puede transformarlos en el tipo que quiera como se ve en el Tema 3.
TYPEALIAS
Los alias nos permiten referirnos a partes de nuestro código con nombres más expresivos y sencillos para facilitar la lectura del código. Su sintaxis es la siguiente:
Ejemplos de Typealias
DESESTRUCTURACIÓN
Existen tipos de datos que almacenan en un mismo valor varios datos e incluso estos datos pueden ser de diferentes tipos. Por ejemplo, un Array de Arrays almacena en cada uno de sus elementos un Array con diferentes elementos a su vez. O un mapa que almacena una clave y un valor en cada uno de sus elementos.
Para poder separar estos diferentes datos en variables diferentes se implementó la desestructuración.
La desestructuración de un tipo permite desempacar un valor compuesto por varios datos en diferentes variables. La sintaxis es la siguiente:
Uso del guión bajo
En el caso de que no queramos desestructurar todas las variables, podemos omitir algunas poniendo un guión bajo (_) en el lugar en el que le asignaríamos un nombre:
Funciones de componente
La desestructuración es posible gracias a la existencia de funciones de componentes o funciones componentN()
. Internamente el compilador invoca a estas funciones desde el objeto a desestructurar, con el objetivo de declarar e inicializar múltiples variables.
Last updated