Cos'è Kotlin? Spiegata l'alternativa Java

Kotlin è un linguaggio di programmazione "pragmatico" di tipo statico, gratuito, open source, generico, inizialmente progettato per JVM (Java Virtual Machine) e Android che combina funzionalità di programmazione orientate agli oggetti e funzionali. È incentrato su interoperabilità, sicurezza, chiarezza e supporto per gli strumenti. Sono in produzione anche versioni di Kotlin destinate a JavaScript ES5.1 e codice nativo (che utilizza LLVM) per un numero di processori.

Kotlin è nato da JetBrains, la società dietro IntelliJ IDEA, nel 2010, ed è open source dal 2012. Il team di Kotlin ha attualmente più di 90 membri a tempo pieno da JetBrains e il progetto Kotlin su GitHub ha più di 300 collaboratori. JetBrains utilizza Kotlin in molti dei suoi prodotti, incluso il suo fiore all'occhiello IntelliJ IDEA.

Kotlin come linguaggio Java più conciso

A prima vista, Kotlin sembra una versione più concisa e semplificata di Java. Considera lo screenshot qui sopra, dove ho convertito automaticamente un esempio di codice Java (a sinistra) in Kotlin. Si noti che la ripetizione insensata inerente alla creazione di un'istanza di variabili Java è scomparsa. L'idioma di Java

StringBuilder sb = new StringBuilder ();

Diventa in Kotlin

val sb = StringBuilder ()

Puoi vedere che le funzioni sono definite con la funparola chiave e che i punti e virgola sono ora facoltativi quando sono presenti i nuovi caratteri. La valparola chiave dichiara una proprietà di sola lettura o una variabile locale. Allo stesso modo, la varparola chiave dichiara una proprietà modificabile o una variabile locale.

Tuttavia, Kotlin è fortemente tipizzato. Le parole chiave vale varpossono essere utilizzate solo quando il tipo può essere dedotto. Altrimenti devi dichiarare il tipo. L'inferenza di tipo sembra migliorare con ogni versione di Kotlin.

Dai un'occhiata alla dichiarazione della funzione nella parte superiore di entrambi i riquadri. Il tipo restituito in Java precede il prototipo, ma in Kotlin succede al prototipo, delimitato con due punti come in Pascal.

Non è del tutto ovvio da questo esempio, ma Kotlin ha attenuato il requisito di Java che le funzioni siano membri di una classe. In Kotlin, le funzioni possono essere dichiarate al livello più alto in un file, localmente all'interno di altre funzioni, come una funzione membro all'interno di una classe o di un oggetto e come una funzione di estensione. Le funzioni di estensione forniscono la capacità simile a C # di estendere una classe con nuove funzionalità senza dover ereditare dalla classe o utilizzare qualsiasi tipo di modello di progettazione come Decorator.

Per i fan di Groovy, Kotlin implementa i builder; infatti, i costruttori di Kotlin possono essere controllati sul tipo. Kotlin supporta proprietà delegate, che possono essere utilizzate per implementare proprietà pigre, proprietà osservabili, proprietà soggette a veto e proprietà mappate.

Molti meccanismi asincroni disponibili in altre lingue possono essere implementati come librerie utilizzando le coroutine di Kotlin. Ciò include async/ awaitda C # ed ECMAScript, canali e selezione da Vai e generators/ yieldda C # e Python.

Programmazione funzionale in Kotlin

Consentire funzioni di primo livello è solo l'inizio della storia della programmazione funzionale per Kotlin. Il linguaggio supporta anche funzioni di ordine superiore, funzioni anonime, lambda, funzioni inline, chiusure, ricorsione in coda e generici. In altre parole, Kotlin ha tutte le caratteristiche ei vantaggi di un linguaggio funzionale. Ad esempio, considera i seguenti idiomi funzionali di Kotlin.

Filtrare un elenco in Kotlin

val positives = list.filter {x -> x> 0}

Per un'espressione ancora più breve, usa itquando c'è un solo parametro nella funzione lambda:

val positives = list.filter {it> 0}

Attraversando una mappa / elenco di coppie a Kotlin

for ((k, v) nella mappa) {println ("$ k -> $ v")}

kv può essere chiamato qualsiasi cosa.

Utilizzo di intervalli in Kotlin

for (i in  1..100) {...} // intervallo chiuso: include 100

for (i in  1 until 100) {...} // intervallo semiaperto: non include 100

per (x in  2..10 passaggio 2) {...}

per (x in  10 downTo 1) {...}

se (x in  1..10) {...}

Gli esempi precedenti mostrano la  for parola chiave e l'uso di intervalli.

Anche se Kotlin è un vero e proprio linguaggio di programmazione funzionale, conserva la maggior parte della natura orientata agli oggetti di Java come stile di programmazione alternativo, che è molto utile quando si converte il codice Java esistente. Kotlin ha classi con costruttori, insieme a classi interne annidate, interne e anonime, e ha interfacce come Java 8. Kotlin non ha una newparola chiave. Per creare un'istanza di classe, chiama il costruttore proprio come una normale funzione. Lo abbiamo visto nello screenshot qui sopra.

Kotlin ha una singola eredità da una superclasse denominata e tutte le classi Kotlin hanno una superclasse predefinita Any, che non è la stessa della classe base Java java.lang.Object. Anycontiene solo tre funzioni membro predefiniti: equals(), hashCode()e toString().

Le classi di Kotlin devono essere contrassegnate con la openparola chiave per consentire ad altre classi di ereditare da esse; Le classi Java sono in qualche modo l'opposto, poiché sono ereditabili a meno che non siano contrassegnate con la finalparola chiave. Per sostituire un metodo della superclasse, il metodo stesso deve essere contrassegnato opene il metodo della sottoclasse deve essere contrassegnato override. Questo è tutto un pezzo con la filosofia di Kotlin di rendere le cose esplicite piuttosto che fare affidamento sui valori predefiniti. In questo caso particolare, posso vedere dove il modo di Kotlin di contrassegnare esplicitamente i membri della classe base come aperti all'ereditarietà e membri della classe derivata come sostituzioni evita diversi tipi di errori Java comuni.

Caratteristiche di sicurezza in Kotlin

Parlando di evitare errori comuni, Kotlin è stato progettato per eliminare il pericolo di riferimenti a puntatori nulli e semplificare la gestione dei valori nulli. Lo fa rendendo nullillegale per i tipi standard, aggiungendo tipi nullable e implementando notazioni di collegamento per gestire i test per null.

Ad esempio, una variabile normale di tipo  non può contenere  :String null

var a: String = "abc"

a = null // errore di compilazione

Se è necessario consentire i valori null, ad esempio per contenere i risultati di una query SQL, è possibile dichiarare un tipo nullable aggiungendo un punto interrogativo al tipo, ad es String?.

var  b: String?

b = null  // ok

Le protezioni vanno un po 'oltre. È possibile utilizzare un tipo non nullable con impunità, ma è necessario testare un tipo nullable per i valori null prima di usarlo.

Per evitare la grammatica verbosa normalmente necessaria per i test nulli, Kotlin introduce una chiamata sicura , scritta ?.. Ad esempio, restituisce se non lo è e altrimenti. Il tipo di questa espressione è .b?.length b.lengthbnullnullInt?

In altre parole, b?.lengthè una scorciatoia per if (b != null) b.length else null. Questa sintassi concatena bene, eliminando un bel po 'di logica prolissa, specialmente quando un oggetto è stato popolato da una serie di query di database, ognuna delle quali potrebbe non essere riuscita. Ad esempio, bob?.department?.head?.namerestituirebbe il nome del capo dipartimento di Bob se Bob, il dipartimento e il capo dipartimento sono tutti non nulli.

Per eseguire una determinata operazione solo per valori non nulli, è possibile utilizzare l'operatore di chiamata sicura ?.insieme a  let:

val listWithNulls: List = listOf ("A", null)

for (item in listWithNulls) {

      elemento? .let {println (it)} // stampa A e ignora null}

Spesso si desidera restituire un valore valido ma speciale da un'espressione nullable, in genere in modo da poterlo salvare in un tipo non nullable. C'è una sintassi speciale per questo chiamato operatore Elvis (non scherzo), scritto ?:.

val l = b? .length?: -1

è l'equivalente di 

val l: Int = if (b! = null) b. lunghezza else -1

Allo stesso modo, Kotlin omette le eccezioni controllate di Java, che sono condizioni lanciabili che devono essere catturate. Ad esempio, la firma JDK

Appendable append (CharSequence csq) genera  IOException;

richiede di catturare IOExceptionogni volta che chiami un appendmetodo:

provare {

  log.append (messaggio)

}

catch (IOException e) {

  // Fai qualcosa con l'eccezione

}

I progettisti di Java hanno pensato che questa fosse una buona idea, ed è stata una vittoria netta per i programmi giocattolo, a condizione che i programmatori implementassero qualcosa di sensato nella catchclausola. Troppo spesso in grandi programmi Java, tuttavia, si vede il codice in cui l'obbligatoria catchla clausola contiene solo un commento: //todo: handle this. Questo non aiuta nessuno e le eccezioni controllate si sono rivelate una perdita netta per i programmi di grandi dimensioni.

Kotlin coroutines

Le coroutine in Kotlin sono essenzialmente thread leggeri. Inizi con il launchcoroutine builder nel contesto di alcuni CoroutineScope. Uno degli ambiti di coroutine più utili è runBlocking{}, che si applica all'ambito del suo blocco di codice.

importa kotlinx.coroutines. *

fun main () = runBlocking {// this: CoroutineScope

    launch {// lancia una nuova coroutine nell'ambito di runBlocking

        delay (1000L) // ritardo non bloccante per 1 secondo

        println ("World!")

    }

    println ("Ciao")

}

Questo codice produce il seguente output, con un secondo di ritardo tra le righe:

Ciao,

Mondo!

Kotlin per Android

Fino a maggio 2017, gli unici linguaggi di programmazione ufficialmente supportati per Android erano Java e C ++. Google ha annunciato il supporto ufficiale per Kotlin su Android al Google I / O 2017 e, a partire da Android Studio 3.0, Kotlin è integrato nel set di strumenti di sviluppo Android. Kotlin può essere aggiunto alle versioni precedenti di Android Studio con un plug-in.

Kotlin compila lo stesso codice byte di Java, interagisce con le classi Java in modo naturale e condivide i suoi strumenti con Java. Poiché non vi è alcun sovraccarico per chiamare avanti e indietro tra Kotlin e Java, l'aggiunta di Kotlin in modo incrementale a un'app Android attualmente in Java ha perfettamente senso. I pochi casi in cui l'interoperabilità tra Kotlin e il codice Java manca di grazia, come le proprietà di solo set Java, si incontrano raramente e si risolvono facilmente.

Pinterest era il poster per le app Android scritte in Kotlin già nel novembre 2016 ed è stato menzionato in modo prominente al Google I / O 2017 come parte dell'annuncio di Kotlin. Inoltre, al team di Kotlin piace citare le app Evernote, Trello, Square e Coursera per Android.

Kotlin contro Java

La domanda se scegliere Kotlin o Java per il nuovo sviluppo è emersa molto nella comunità Android dall'annuncio di Google I / O, anche se le persone stavano già ponendo la domanda nel febbraio 2016 quando Kotlin 1.0 è stato rilasciato. La risposta breve è che il codice Kotlin è più sicuro e più conciso del codice Java e che i file Kotlin e Java possono coesistere nelle app Android, in modo che Kotlin non sia utile solo per le nuove app, ma anche per espandere le app Java esistenti.

L'unico argomento convincente che ho visto per la scelta di Java su Kotlin sarebbe per il caso dei neofiti dello sviluppo Android completo. Per loro, potrebbe esserci una barriera da superare dato che, storicamente, la maggior parte della documentazione e degli esempi Android sono in Java. D'altra parte, convertire Java in Kotlin in Android Studio è una semplice questione di incollare il codice Java in un file Kotlin.

Per quasi tutti gli altri che si occupano di sviluppo Android, i vantaggi di Kotlin sono convincenti. Il tempo tipico indicato per uno sviluppatore Java per imparare Kotlin è di poche ore, un piccolo prezzo da pagare per eliminare gli errori di riferimento nulli, abilitare le funzioni di estensione, supportare la programmazione funzionale e aggiungere coroutine. La tipica stima approssimativa indica una riduzione di circa il 40% nel numero di righe di codice da Java a Kotlin.