Kotlin (liberado por JetBrains) es un lenguaje de programación que opera bajo la máquina virtual de java (JVM) con unas características interesantes que simpatizan con un estilo sencillo y funcional, su interoperalidad con Java lo hace atractivo para entenderse perfectamente con sistemas informáticos ya existentes (en Java), además de ser usado para programar bajo Android, también tiene características de integración nativa (Kotlin-Native
basada en LLVM) y para la web (KotlinJS
), posibilitando programar para el navegador como sustituto de Javascript, planteando desde su filosofía el concepto de multiplataforma a un nuevo nivel (aunque quién guste de dejar quieto el navegador con Javascript podrá tomar su propia opinión). De hecho, JetBrains ha liberado su propia tecnología para móviles denominada Kotlin Multiplatform Mobile que atienda la lógica de las aplicaciones móviles dejando la implementación de un componente estrictamente visual en el lenguaje nativo según corresponda (por ejemplo: Swift para iOS, el mismo Kotlin para Android).
Esta es una referencia ágil para quién tenga nociones de programación o codifique con algún otro lenguaje, también a modo de repaso y uso frecuente. Siendo así, tener esta información como memoria te resultará simple de acceder a los fundamentos, incluso como prueba de concepto sobre el lenguaje.
package hello
fun main(args: Array<String>) {
println("Hi there!")
}
package project
class App {
fun print() {
println("Hi there!")
}
}
fun main(args: Array<String>) {
App().print()
}
Para quien tenga habilidades, experticia en programación y/o requiera agilidad en conceptos técnicos, pueden resumirse los siguientes tips esenciales del lenguaje:
Int
, Double
, Boolean
, String
, List
, Array
. Las variables se definen con var
o val
(si no cambia o no muta) y se puede asignar el valor directamente sin necesidad de especificar el tipo de datos. Si requiere especificarse el tipo de datos se usa :
y luego el tipo.fun
, luego los parámetros van entre paréntesis (...)
, continuando con el nombre del parámetro, el caracter :
que separa el tipo de datos posteriormente (y separando los parámetros con coma ,
). El tipo de datos a retornar va también después de :
. Además, se usa return
para retornar un valor. La función principal de un programa se denomina main
.{}
. Las sentencias pueden terminar sin punto y coma, siendo solamente necesario para separar y admitir varias sentencias en la misma línea (por lo demás, no se usa).C
, Java
, Javascript
, Dart
, es decir que se cuenta con una anatomía cercana para el uso de if
, for
, while
, incluso para el manejo de excepciones (try
).constructor
y la clase se define con la palabra reservada class
y el nombre que debe iniciar en mayúscula. También existe un bloque o constructor de inicialización init {...}
.?.
. Esta característica ha sido un gran diferenciador del lenguaje respecto a otros, y evita excepciones frecuentes que requieren mayor control y código en un programa con lenguaje Java
.Java
, incorpora data class
para definir, de modo abreviado y máginamente, una clase que representa una estructura de datos con métodos para acceder a éstos. Serializar datos en JSON no es natural al lenguaje pero básicamente consiste en establecer el data class
con la anotación Serializable
, se importa la librería respectiva (kotlinx.serialization
) y se usa Json.encodeToString
o Json.deodeFromString
según corresponda.Por cierto,
Kotlin
brinda interoperabilidad conJava
, por lo que reconoce naturalmente librerías escritas enJava
(sobre laJVM
), por ejemplo los conectores a las bases de datos, y también puede incorporar trozos deSQL
.
Si tienes conocimiento en Javascript
u otro lenguaje, puede ser útil un sencillo escenario de comparación que nos da una referencia inmediata de Kotlin
.
Concepto | Javascript | Kotlin |
---|---|---|
Variable | let variable = ‘Ana’ | var variable = “Ana” |
Función | function pow(x) { } | fun pow(x: Int): Int { } |
Condición | if (i == 1) { } | if (i == 1) { } |
Ciclo For | for (let i = 0; i < 10; i++) { } | for (i in 0…9) { } |
Excepción | try { } catch(err) { } | try { } catch(err: Exception) { } |
Como puede observarse un programador puede facilmente asimilar la sintaxis de
Kotlin
en poco tiempo.
Se puede declarar variables con las palabras reservadas var y val, esta última para indicar que el valor no cambia o no es mutable.
Ejemplo:
var variable: String = "Ana"
val immutable: String = "Ana"
var n: Int = 0
Si estás iniciando en la programación bajo la JVM
, una manera sencilla de comprender qué son los paquetes es verlos como las carpetas agrupadoras para organizar tu aplicación, y en muchas ocasiones pueden establecerse con un estilo semejante a un subdominio en internet de modo inverso, por ejemplo, si se piensa en un subdominio app.mycompany.com
el paquete podría ser com.mycompany.app
, de otro modo, se puede usar una carpeta de estructura simple que se refiera al nombre o alias del proyecto.
package project
import java.util.*
...
fun plus1(a: Int, b: Int) = a + b
fun plus2(a: Int, b: Int): Int {
return a + b
}
// Esto es un comentario de fin de línea
/*
Este es un comentario de bloque
*/
if (i == 1) {
println("one")
}
else if (i == 2) {
println("two")
}
else {
println("aha")
}
for (item in list) {
println(item)
}
for (index in list.indices) {
println(list[index])
}
for (index in 0 until 10) {
println(index)
}
Puede interrumpirse un ciclo con la sentencia
break
o dar el paso a la siguiente iteración con la setenciacontinue
.
var i = 0
while (i < 10) {
i++
}
var i = 0
do {
i++
}
while (i < 10)
var i = 0
when (i) {
1 -> println("one")
2 -> println("two")
else -> println("aha")
}
list.forEach {
println(it)
}
La expresion
it
es en realidad una palabra reservada del lenguage para obtener el elemento conforme al ámbito
try {
...
}
catch (e: Exception) {
...
}
finally {
...
}
Puedes usar
throw
(por ejemplo:throw Exception()
) para forzar el lanzamiento de un error.
La programación orientada a objetos (OOP) tiene su propia base de conceptos que abre un capítulo aparte para su comprensión, se puede decir que se pasa de pensar en funciones a clases que agrupan métodos (funciones) y propiedades (variables), siendo de gran útilidad para la reutilización de código. Como referencia simplemente se presenta la anatomía de una clase.
class Shape(val name: String) {
private var sides: Int? = null
constructor(name: String, sides: Int) : this(name) {
this.sides = sides
}
}
open class Base {
open fun run() { ... }
}
class Some : Base() {
override fun run() {
...
}
}
data class Person(val name: String, val age: Int)
Para lograr json
en Kotlin se usan librerías, como Jackson, que permiten mapear un objeto a una cadena que representa el json
o viceversa. Veremos algun ejemplo basado en la siguiente clase:
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import kotlinx.serialization.Serializable
@Serializable
class Person(val name: String, val age: Int)
fun main() {
val person = Person( "Andrey", 27 )
val encodedJson = Json.encodeToString(person)
val decodedJson = Json.decodeFromString<Person>(encodedJson)
}
Para instalar Kotlin bajo Windows se puede descargar desde el sitio oficial y se agrega la ruta de la carpeta bin
en el PATH
del sistema. También puede usarse scoop
en Windows (si esta previamente instalado) usando PowerShell con la sentencia:
scoop install kotlin
Para Linux se puede usar lo siguiente:
sdk install kotlin
Para macOS se usa Homebrew (previamente instalado) y se ejecuta:
brew install kotlin
kotlin -version
nos puede mostrar la versión instalada
Para compilar una aplicación el comando siguiría un formato, dónde program
representaría el nombre respectivo de nuestro programa. Veamos a continuación:
kotlinc program.kt -include-runtime -d program.jar
Para correr el programa se podría usar el siguiente comando:
java -jar program.jar
Maven es una de los gestores de paquetes de Java bien reconocidos, y también se usa para Kotlin. Un proyecto con Maven consiste en una archivo denominado pom.xml
que tiene algunas secciones. Un ejemplo de un archivo pom.xml
para un proyecto bajo Kotlin sería el siguiente:
<properties>
<kotlin.version>1.6.10</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
<configuration>
<jvmTarget>1.8</jvmTarget>
</configuration>
</plugin>
</plugins>
</build>
</build>
Esta configuración inicial nos permitirá compilar nuestro proyecto. Sin embargo, debe interpretarse considerando que, si existe un archivo previo, debemos usar los fragmentos respectivos del contenido en formato
xml
.
Nótese que en el elementojvmTarget
se debe especificar la versión de JDK, en este caso 1.8 pero podría ser la versión 11.
Ktor (liberado por JetBrains) es un marco de trabajo para desarrollo Web con Kotlin que opera bajo la máquina virtual de java (JVM) siendo sencillo y abierto a opiniones, por ejemplo, puede integrarse con Netty o Jetty para un uso simplificado y escalar, incluso en un contenedor de Servlets como Tomcat.
import io.ktor.application.*
import io.ktor.http.*
import io.ktor.response.*
import io.ktor.routing.*
import io.ktor.server.engine.embeddedServer
import io.ktor.server.netty.Netty
fun main (args: Array<String>) {
val server = embeddedServer(Netty, 9000) {
routing {
get("/") {
call.respondText("Hi there!", ContentType.Text.Plain)
}
}
}.start(wait = true)
}
Continuando con tecnología para programar un servidor web sencillo, encontramos el proyecto Javalin que usa Jetty. Veamos el ejemlo:
import io.javalin.Javalin
fun main(args: Array<String>) {
val port = 8000
val app = Javalin.create().start(port)
app.get("/") { ctx -> ctx.result("Hi there!") }
}
En el siguiente ejemplo, usaremos ProcessBuilder para invocar una sentencia desde el sistema operativo, esto puede ser últil para gestionar scripts o tareas de servidor con sistemas como Linux y macOS (o en Windows usando WSL). En el ejemplo esencial podemos ilustrar un código como el siguiente:
package com.example
import java.io.BufferedReader
import java.io.IOException
import java.io.InputStreamReader
class ShellRemoteCalled() {
fun remoteCalled() {
val processBuilder = ProcessBuilder()
processBuilder.command("python3", "test.py")
try {
val rpc = processBuilder.start()
val reader = BufferedReader(InputStreamReader(rpc.inputStream))
var result: String? = ""
var line: String?
while (reader.readLine().also { line = it } != null) {
result += line
}
val exitCode = rpc.waitFor()
println("\nShellRemoteCalled output : $result")
println("Exited with error code : $exitCode")
} catch (e: IOException) {
println("\nException occurs")
e.printStackTrace()
} catch (e: InterruptedException) {
println("\nInterrupted")
e.printStackTrace()
}
}
}
fun main() { // Could have args: Array<String>
ShellRemoteCalled().remoteCalled()
}
test.py
representa un script en Python (puede consistir simplemente en un saludo:print("Hello")
)
Para lazar nuestro ejercicio ejecutamos lo siguiente:
kotlinc ShellRemoteCalled.kt -include-runtime -d ShellRemoteCalled.jar
java -jar ShellRemoteCalled.jar
© 2019 by César Arcila