Kotlin (linguaxe de programación)

Kotlin (/ˈkɒtlɪn/) é unha linguaxe de programación de alto nivel multiplataforma, de tipado estático, e de propósito xeral con inferencia de tipos. Kotlin está deseñado para interoperar totalmente con Java, e a versión JVM da biblioteca estándar de Kotlin depende da biblioteca de clases de Java, pero a inferencia de tipos permite que a súa sintaxe sexa máis concisa. Kotlin está dirixido principalmente á JVM, pero tamén compila en JavaScript (por exemplo, para aplicacións web frontend que usan React) ou código nativo a través de LLVM (por exemplo, para aplicación nativas de iOS que comparten lóxica empresarial con aplicacións de Android). Os custos de desenvolvemento da linguaxe corren a cargo de JetBrains, mentres que a Fundación Kotlin protexe a marca rexistrada Kotlin.

O 7 de maio de 2019, Google anunciou que a linguaxe de programación Kotlin se convertera na súa linguaxe preferida para os desenvolvedores de aplicacións de Android. Desde o lanzamento de Android Studio 3.0 en outubro de 2017, Kotlin incluíuse como alternativa ao compilador estándar de Java. O compilador Kotlin de Android emite bytecode de Java 8 por defecto (que se executa en calquera JVM posterior), pero permite orientarse dende Java 9 ata Java 20 para optimizar, ou permite máis funcionalidades; ten compatibilidade con interoperabilidade de clases de rexistro bidireccional para JVM, introducida en Java 16, considerada estable a partir de Kotlin 1.5.

Kotlin ten compatibilidade coa web con Kotlin/JS, a través dun backend intermedio baseado en representacións que foi declarado estable desde a versión 1.8, lanzada en decembro de 2022. Kotlin/Native (por exemplo, compatibilidade con Apple silicon) foi declarado estable desde a versión 1.9.20, lanzada en novembro de 2023.

 Historia 
miniatura|Mascota de Kotlin chamada Kodee (versión regular)
miniatura|Mascota de Kotlin chamada Kodee (versión pequena)

 Nome 
O nome deriva da illa Kotlin, unha illa rusa no Golfo de Finlandia, preto de San Petersburgo. Andrey Breslav,  antigo deseñador principal de Kotlin, mencionou que o equipo decidiu nomeala como unha illa, imitando a linguaxe de programación Java que comparte nome coa illa indonesia de Xava.

 Desenvolvemento 
A primeira confirmación no repositorio Git de Kotlin foi o 8 de novembro de 2010.

En xullo de 2011, JetBrains presentou o Proxecto Kotlin, unha nova linguaxe para a JVM, que levaba un ano en desenvolvemento. O líder de JetBrains, Dmitry Jemerov, dixo que a maioría das linguaxes non tiñan as características que buscaban, coa excepción de Scala. Non obstante, citou o lento tempo de compilación de Scala como unha deficiencia. Un dos obxectivos declarados de Kotlin é compilar tan rápido como Java. En febreiro de 2012, JetBrains publicou o proxecto en código aberto baixo a licenza Apache 2.

JetBrains esperaba que Kotlin impulsase as vendas de IntelliJ IDEA.

Kotlin 1.0 foi lanzado o 15 de febreiro de 2016. Esta considérase a primeira versión oficialmente estable, e JetBrains comprometeuse coa compatibilidade con versións anteriores a longo prazo a partir desta versión.

No Google I/O de 2017, Google anunciou soporte de primeira clase para Kotlin en Android. O 7 de maio de 2019, Google anunciou que a partir de ese momento, Kotlin era a súa linguaxe preferida para os desenvolvedores de aplicacións de Android.

 Deseño 
O xefe de desenvolvemento, Andrey Breslav, afirmou que Kotlin está deseñado para ser unha linguaxe orientada a obxectos de potencia industrial e unha "mellor linguaxe" que Java, pero que aínda así sexa totalmente interoperable co código Java, o que permite ás empresas facer unha migración gradual de Java a Kotlin.

Os puntos e coma  son opcionais como terminador de instrucións; na maioría dos casos un salto de liña é suficiente para que o compilador deduza que a instrución rematou.

As declaracións de variables e as listas de parámetros de Kotlin teñen o tipo de dato despois do nome da variable (e cun separador de dous puntos), de xeito similar a Ada, BASIC, Pascal, TypeScript e Rust. Isto, segundo un artigo de Roman Elizarov, actual xefe do proxecto, resulta na aliñación dos nomes das variables e é máis agradable á vista, especialmente cando hai unhas poucas declaracións de variables sucesivas e un ou máis dos tipos son demasiado complexos para a inferencia de tipos ou necesitan ser declarados explicitamente para que os lectores humanos os entendan.

A influencia de Scala  pódese ver no amplo soporte tanto para a programación orientada a obxectos como para a funcional e nunha serie de características específicas: 

 Existe unha distinción entre variables mutables e inmutábeis (palabra clave var vs val).
 Todas as clases son públicas e finais (non herdables) por defecto.
 As funcións e os métodos admiten argumentos predeterminados, listas de argumentos de lonxitude variable e argumentos nomeados.

Kotlin 1.3 engadiu soporte para contratos, que son estables para as declaracións estándar da biblioteca, pero aínda experimentais para as declaracións definidas polo usuario. Os contratos están inspirados no paradigma de programación deseño por contrato de Eiffel.

Seguindo ScalaJS, o código de Kotlin pódese transpilar a JavaScript, o que permite a interoperabilidade entre o código escrito nas dúas linguaxes. Isto pódese usar para escribir aplicacións web completas en Kotlin ou para compartir código entre un backend de Kotlin e un frontend de JavaScript.

 Sintaxe 

 Estilo de programación procedimental 
Kotlin relaxa a restrición de Java de permitir que os métodos e variables estáticos existan só dentro dun corpo de clase. Os obxectos e funcións estáticos pódense definir no nivel superior do paquete sen necesidade dun nivel de clase redundante. Para compatibilidade con Java, Kotlin proporciona unha anotación JvmName que especifica un nome de clase usado cando se visualiza o paquete desde un proxecto Java. Por exemplo, @file:JvmName("JavaClassName").

 Punto de entrada principal 
Do mesmo xeito que en C, C++, C#, Java, e Go, o punto de entrada a un programa de Kotlin é unha función chamada "main", á que se lle pode pasar unha lista que contén calquera argumento da liña de comandos. Isto é opcional desde Kotlin 1.3. Admítese a interpolación de cadeas ao estilo shell de Perl, PHP, e Unix. Tamén se admite a inferencia de tipo.// Exemplo Hello, World!
fun main() {
    val scope = "World"
    println("Hello, $scope!")
}fun main(args: Array<String>) {
    for (arg in args)
        println(arg)
}

 Funcións de extensión 
De xeito similar a C#, Kotlin permite engadir unha función de extensión a calquera clase sen as formalidades de crear unha clase derivada con novas funcións. Unha función de extensión ten acceso a toda a interface pública dunha clase, que pode usar para crear unha nova interface de función para unha clase de destino. Unha función de extensión aparecerá exactamente como unha función da clase e mostrarase na inspección de finalización de código das funcións da clase. Por exemplo:package com.example.myStringExtensions

fun String.lastChar(): Char = get(length - 1)

>>> println("Kotlin".lastChar())

Ao colocar o código anterior no nivel superior dun paquete, a clase String amplíase para incluír unha función lastChar que non estaba incluída na definición orixinal da clase String.// Sobrecarga do operador '+' usando unha función de extensión
operator fun Point.plus(other: Point): Point {
    return Point(x + other.x, y + other.y)
}

>>> val p1 = Point(10, 20)
>>> val p2 = Point(30, 40)
>>> println(p1 + p2)
Point(x=40, y=60)
 Funcións de ámbito 
Kotlin ten cinco funcións de ámbito, que permiten cambiar o ámbito dentro do contexto dun obxecto. As funcións de ámbito son let, run, with, apply, e also.

 Desempaquetar argumentos co operador de dispersión 
Semellante a Pitón, o asterisco de operador estendido (*)  desempaqueta o contido dunha lista como argumentos individuais para unha función, por exemplo:fun main(args: Array<String>) { 
    val list = listOf("args: ", *args)
    println(list)
}
 Desestruturación de declaracións 
As declaracións de desestruturación descompoñen un obxecto en varias variables á vez, por exemplo, un obxecto de coordenadas 2D pode desestruturarse en dous enteiros, x e y.

Por exemplo, o obxecto Map.Entry admite a desestruturación para simplificar o acceso aos seus campos de clave e valor:
Non se debe confundir co método destrutor común nas linguaxes orientadas a obxectos. for ((key, value) in map)
    println("$key: $value")

 Funcións aniñadas 
Kotlin permite declarar funcións locais dentro doutras funcións ou métodos.class User(val id: Int, val name: String, val address: String)

fun saveUserToDb(user: User) {
    fun validate(user: User, value: String, fieldName: String) {
        require(value.isNotEmpty()) { "Can't save user ${user.id}: empty $fieldName" }
    }

    validate(user, user.name, "Name") 
    validate(user, user.address, "Address")
    // Gardar o usuario na base de datos 
    ...
}

 As clases son finais por defecto 
En Kotlin, para derivar unha nova clase a partir dun tipo de clase base, a clase base debe marcarse explicitamente como "open". Isto contrasta coa maioría das linguaxes orientadas a obxectos, como Java, onde as clases están abertas por defecto.

Exemplo dunha clase base que está aberta para derivar unha nova subclase a partir dela:// open na clase significa que esta clase permitirá clases derivadas
open class MegaButton {

    // se non hai un open nunha función significa que 
    // o comportamento polimórfico desactívase se a función se sobrescribe na clase derivada
    fun disable() { ... }

    // open nunha función significa que
    // o comportamento polimórfico permítese se a función se sobrescribe na clase derivada
    open fun animate() { ... }
}

class GigaButton: MegaButton() {

    // Uso explícito da palabra clave override necesario para sobrescribir unha función na clase derivada
    override fun animate() { println("Giga Click!") } 
}

 As clases abstractas son abertas por defecto 
As clases abstractas definen funcións abstractas ou estruturas puramente virtuais de funcións que se definirán nunha clase derivada. As clases abstractas están abertas por defecto.// Non se precisa a palabra clave open aquí, xa está aberta por defecto
abstract class Animated {

    // Esta función virtual xa está aberta por defecto tamén
    abstract fun animate()

    open fun stopAnimating() { }

    fun animateTwice() { }
}

 As clases son públicas por defecto 
Kotlin proporciona as seguintes palabras clave para restrinxir a visibilidade das declaracións de nivel superior (como as clase) e dos membros da clase: public, internal, protected e private.

Cando se aplica a un membro da clase:
Palabra claveVisibilidadepublic (por defecto)En todas partesinternalDentro dun móduloprotectedDentro de subclasesprivateDentro dunha clase
Cando se aplica a unha declaración de nivel superior:
Palabra claveVisibilidadepublic (por defecto)En todas partesinternalDentro dun móduloprivateDentro dun ficheiro
Exemplo:// A clase só é visible para o módulo actual
internal open class TalkativeButton {
    // o método só é visible para a clase actual
    private fun yell() = println("Hey!")
    // o método é visible para a clase actual e as clases derivadas
    protected fun whisper() = println("Let's talk!")
}
internal class MyTalkativeButton: TalkativeButton() {
    fun utter() = super.whisper()
}
MyTalkativeButton().utter()
 Construtor primario vs. construtores secundarios 
Kotlin admite a especificación dun "construtor primario" como parte da propia definición da clase, que consiste nunha lista de argumentos despois do nome da clase. Esta lista de argumentos admite unha sintaxe ampliada nas listas de argumentos de funcións estándar de Kotlin que permite a declaración de propiedades da clase no construtor primario, incluíndo atributos de visibilidade, extensibilidade e mutabilidade. Ademais, ao definir unha subclase, as propiedades das superinterfaces e superclases poden ser anuladas no construtor primario.// Exemplo dunha clase que usa a sintaxe do construtor primario
// (Só se require un construtor para esta clase)
open class BaseUser(open var isSubscribed: Boolean)
open class PowerUser(protected val nickname: String, final override var isSubscribed: Boolean = true):BaseUser(isSubscribed) { }Non obstante, nos casos nos que se necesita máis dun construtor para unha clase, pódese definir un construtor máis xeral usando a sintaxe do construtor secundario, que se asemella moito á sintaxe do construtor utilizada na maioría das linguaxes orientadas a obxectos como C++, C# e Java.// Exemplo dunha clase usando a sintaxe do construtor secundario
// (requírese máis dun construtor para esta clase)
class Context
class AttributeSet
open class View(ctx:Context) {
    constructor(ctx: Context, attr: AttributeSet): this(ctx)
}
class MyButton : View {
    // Constructor #1 
    constructor(ctx: Context) : super(ctx) { 
    } 
    // Constructor #2
    constructor(ctx: Context, attr: AttributeSet) : super(ctx, attr) {
        // ... 
    }
}

 Clases seladas 
As clases e interfaces seladas restrinxen as xerarquías de subclases, o que significa máis control sobre a xerarquía de herdanza.

Declaración da interface e clase seladas:sealed interface Expr
sealed class JobTodas as subclases da clase selada defínense no momento da compilación. Non se poden engadir novas subclases despois da compilación do módulo que ten a clase selada. Por exemplo, unha clase selada nun ficheiro jar compilado non se pode subclasificar.sealed class Vehicle
data class Car(val brandName: String, val owner: String, val color: String): Vehicle()
class Bike(val brandName: String, val owner: String, val color: String): Vehicle()
class Tractor(val brandName: String, val owner: String, val color: String): Vehicle()
val kiaCar = Car("KIA", "John", "Blue")
val hyundaiCar = Car("Hyundai", "Britto", "Green")

 Clases de datos 
A construción data class de Kotlin define clases cuxo propósito principal é almacenar datos, de xeito similar aos tipos record de Java. Do mesmo xeito que os tipos record de Java, a construción é similar ás clases normais, agás que os métodos clave equals, hashCode e toString xéranse automaticamente a partir das propiedades da clase. A diferenza dos rexistros de Java, as clases de datos están abertas para a herdanza.

 Shell interactiva de Kotlin 
$ kotlinc-jvm
type :help for help; :quit for quit
>>> 2 + 2
4
>>> println("Hello, World!")
Hello, World!

 Kotlin como linguaxe de scripting 
Kotlin tamén se pode usar como linguaxe de scripting. Un script é un ficheiro fonte de Kotlin que usa a extensión de ficheiro .kts con código fonte executable no ámbito de nivel superior:// list_folders.kts
import java.io.File
val folders = File(args[0]).listFiles { file -> file.isDirectory() }
folders?.forEach(::println)Os scripts pódense executar pasando a opción -script e o ficheiro de script correspondente ao compilador.$ kotlinc -script list_folders.kts "path_to_folder_to_inspect"

 Seguridade con Null 
Kotlin fai unha distinción entre tipos de datos que poden ser null e os que non poden selo. Todos os obxectos que poden ser null deben declararse cun sufixo "?" despois do nome do tipo. As operacións en obxectos que poden ser null requiren un coidado especial por parte dos desenvolvedores: débese realizar unha comprobación null antes de usar o valor, xa sexa explicitamente ou coa axuda dos operadores seguros de Kotlin:

  (o operador de navegación segura) pódese usar para acceder de forma segura a un método ou propiedade dun obxecto posiblemente null. Se o obxecto é null, o método non se chamará e a expresión avalíase como null. Exemplo:
// devolve null se...
// - foo() devolve null,
// - ou se foo() non é null, pero bar() devolve null,
// - ou se foo() e bar() non son null, pero baz() devolve null.
// viceversa, o valor de retorno non é null se e só se foo(), bar() e baz() non son null
foo()?.bar()?.baz()

  (o operador de coalescencia null)  é un operador binario que devolve o primeiro operando, se non é null, se non, o segundo operando. A miúdo chámase operador Elvis, debido á súa semellanza cunha representación de emoticonos de Elvis Presley. fun sayHello(maybe: String?, neverNull: Int) {
    // uso do operador Elvis
    val name: String = maybe ?: "stranger"
    println("Hello $name")
}

 Lambdas 
Kotlin ofrece soporte para funcións de orde superior e funcións anónimas, ou lambdas.// a seguinte función toma unha lambda, f, e execútaa pasándolle a cadea "lambda"
// teña en conta que (String) -> Unit indica unha lambda cun parámetro String e un tipo de retorno Unit
fun executeLambda(f: (String) -> Unit) {
    f("lambda")
} As lambdas decláranse usando chaves, { }. Se unha lambda toma parámetros, decláranse dentro das chaves e seguidos do operador ->.// a seguinte instrución define unha lambda que toma un único parámetro e o pasa á función println
val l = { c : Any? -> println(c) }
// as lambdas sen parámetros poden definirse simplemente usando { }
val l2 = { print("no parameters") }

 Exemplo "Hello World" 
(Tomado e explicado en https://kotlinlang.org/docs/kotlin-tour-hello-world.html)fun main() {
    println("Hello, world!")
    // Hello, world!
}

 Ferramentas 

 Android Studio (baseado en IntelliJ IDEA)  ten soporte oficial para Kotlin, a partir de Android Studio 3.
 Admítese a integración con ferramentas de compilación comúns de Java, incluíndo Apache Maven, Apache Ant, e Gradle.
 Emacs ten un modo Kotlin no seu repositorio de paquetes MELPA.
 JetBrains tamén proporciona un plugin para Eclipse.
 IntelliJ IDEA soporta plug-ins para Kotlin. IntelliJ IDEA 15 foi a primeira versión en incluír o plug-in de Kotlin no instalador de IntelliJ e en proporcionar soporte de Kotlin de inmediato.
 Gradle: Kotlin ten unha integración perfecta con Gradle, unha ferramenta de automatización de compilación.

 Kotlin Multiplataforma 
Kotlin Multiplataforma permite que unha única base de código se centre en varias plataformas como Windows, Linux, web, Android e iOS.

Compose Multiplataforma é un framework de IU multiplataforma baseado en Jetpack Compose. É Jetpack Compose para Android portado a Windows, macOS, Linux, web, e iOS. Jetpack Compose usa un plugin de compilador de Kotlin para transformar funcións compoñibles en elementos de IU. Por exemplo, a función compoñible Text mostra unha etiqueta de texto na pantalla.

Cando Kotlin foi anunciado como unha linguaxe oficial de desenvolvemento de Android en Google I/O en maio de 2017, converteuse na terceira linguaxe totalmente compatible con Android, despois de Java e C++. En 2020, Kotlin era a linguaxe máis utilizada en Android, e Google estima que o 70 % das 1000 aplicacións principais da Play Store estaban escritas en Kotlin. O propio Google tiña 60 aplicacións escritas en Kotlin, incluíndo Maps e Drive. Moitas aplicacións de Android, como Google Home, estaban en proceso de migración a Kotlin e, polo tanto, usan tanto Kotlin como Java. Kotlin en Android considérase beneficioso pola súa seguridade de punteiro nulo, así como polas súas características que fan que o código sexa máis curto e lexible.

Ktor é o primeiro framework Kotlin de Jetbrains para crear aplicacións de servidor e cliente. Spring Framework engadiu oficialmente a compatibilidade con Kotlin coa versión 5, o 4 de xaneiro de 2017. Para dar máis soporte a Kotlin, Spring traduciu toda a súa documentación a Kotlin e engadiu compatibilidade integrada para moitas características específicas de Kotlin, como as coroutines.

En 2020, JetBrains descubriu nunha enquisa a desenvolvedores que usan Kotlin que o 56 % usaba Kotlin para aplicacións móbiles, mentres que o 47 % o usaba para un backend web. Pouco máis dun terzo de todos os desenvolvedores de Kotlin dixeron que estaban a migrar a Kotlin desde outra linguaxe. A maioría dos usuarios de Kotlin tiñan como obxectivo Android (ou calquera outro uso na JVM), e só o 6 % usaba Kotlin Native.

 Adopción 
En 2018, Kotlin foi a linguaxe de máis rápido crecemento en GitHub, con 2,6 veces máis desenvolvedores en comparación con 2017. É a cuarta linguaxe de programación máis querida segundo a enquisa para desenvolvedores de Stack Overflow de 2020.

Kotlin tamén recibiu o premio O'Reilly Open Source Software Conference Breakout Award de 2019.

Moitas empresas e organizacións teñen empregado Kotlin para desenvolver os seus backends:

 Allegro
 Amazon
 Atlassian
 Cash App
 Flux
 Google
 Gradle
 JetBrains
 Meshcloud
 Norwegian Tax Administration
 OLX
 Pivotal
 Rocket Travel
 Shazam
 Zalando

Algunhas empresas e organizacións empregaron Kotlin para o desenvolvemento web:

 Barclay's Bank
 Data2viz
 Fritz2
 JetBrains

Varias empresas declararon publicamente que estaban a usar Kotlin:

 Basecamp
 Corda, un distribuído ledger desenvolveu por un consorcio de bancosbensabidos (como Goldman Sachs, Wells Fargo, J.P. Morgan, Deutsche Bank, UBS, HSBC, BNP Paribas, e Société Générale), ten máis do 90 % de código Kotlin na súa base de código. 
 Coursera
 DripStat
 Duolingo
 Meta
 Netflix
 Pinterest
 Trello
 Uber

 Notas 
 Este artigo contén citas de titoriais de Kotlin publicados baixo a licenza Apache 2.0.

 Véxase tamén 

 Outros artigos 
 Comparación de linguas de programación

Categoría:Linguaxes de programación
Categoría:Programación orientada a obxectos
Categoría:Java (linguaxe de programación)
Categoría:Software
Categoría:Software libre