Kotlin è un linguaggio di programmazione moderno che viene compilato in bytecode Java. È gratuito e open source e promette di rendere la codifica per Android ancora più divertente.
Nell'articolo precedente, hai imparato a conoscere gli intervalli e le raccolte in Kotlin. In questo tutorial, continueremo a imparare la lingua osservando come organizzare il codice usando i pacchetti, e poi passeremo a un'introduzione alle funzioni di Kotlin.
Se hai familiarità con Java, sai che Java usa i pacchetti per raggruppare classi correlate; per esempio, il java.util
il pacchetto ha un numero di classi di utilità utili. I pacchetti sono dichiarati con il pacchetto
parola chiave e qualsiasi file Kotlin con a pacchetto
la dichiarazione all'inizio può contenere dichiarazioni di classi, funzioni o interfacce.
Guardando il codice qui sotto, abbiamo dichiarato un pacchetto com.chikekotlin.projectx
usando il pacchetto
parola chiave. Inoltre, abbiamo dichiarato una classe La mia classe
(discuteremo dei corsi in Kotlin in futuri post) all'interno di questo pacchetto.
pacchetto com.chikekotlin.projectx classe MyClass
Ora, il nome completo per la classe La mia classe
è com.chikekotlin.projectx.MyClass
.
pacchetto com.chikekotlin.projectx fun saySomething (): String return "Quanto lontano?"
Nel codice sopra, abbiamo creato una funzione di primo livello (ci arriveremo a breve). Quindi allo stesso modo di La mia classe
, il nome completo per la funzione di 'qualcosa()
è com.chikekotlin.projectx.saySomething
.
In Kotlin, usiamo il importare
dichiarazione per consentire al compilatore di individuare classi, funzioni, interfacce o oggetti da importare. In Java, d'altra parte, non possiamo importare direttamente funzioni o solo metodi classi o interfacce.
Noi usiamo importare
per accedere a una funzione, interfaccia, classe o oggetto al di fuori del pacchetto in cui è stato dichiarato.
import com.chikekotlin.projectx.saySomething fun main (args: Array) saySomething () // stamperà "Quanto lontano?"
Nello snippet di codice sopra, abbiamo importato la funzione di 'qualcosa()
da un pacchetto diverso, e quindi abbiamo eseguito quella funzione.
Kotlin supporta anche le importazioni di caratteri jolly utilizzando *
operatore. Questo importerà tutte le classi, le interfacce e le funzioni dichiarate nel pacchetto tutto in una volta. Questo non è raccomandato, tuttavia è solitamente meglio rendere esplicite le tue importazioni.
import com.chikekotlin.projectx. *
Quando si dispone di librerie con nomi di classi o funzioni in conflitto (ad esempio, ognuno dichiara una funzione con lo stesso nome), è possibile utilizzare il come
parola chiave per assegnare a quell'entità importata un nome temporaneo.
import com.chikekotlin.projectx.saySomething import com.chikekotlin.projecty.saySomething as projectYSaySomething fun main (args: Array) projectYSaySomething ()
Si noti che il nome temporaneo viene utilizzato solo all'interno del file in cui è stato assegnato.
Una funzione raggruppa una serie di istruzioni di codice che eseguono un'attività. I dettagli dell'implementazione della funzione sono nascosti al chiamante.
In Kotlin, le funzioni sono definite usando divertimento
parola chiave, come mostrato nell'esempio seguente:
fun hello (name: String): String return "Hello $ name" val message = ciao ("Chike") print (messaggio) // stamperà "Hello Chike"
Nel codice sopra, abbiamo definito una funzione semplice Ciao()
con un singolo parametro nome
di tipo Stringa
. Questa funzione restituisce a Stringa
genere. Il formato di definizione dei parametri per le funzioni è nome: tipo
, per esempio. età: Int
, prezzo: doppio
, studente: StudentClass
.
fun hello (name: String): Unit print ("Hello $ name") ciao ("Chike") // stamperà "Hello Chike"
La funzione sopra è simile alla precedente, ma si noti che questa ha un tipo di ritorno Unità
. Perché questa funzione non restituisce alcun valore significativo per noi: stampa semplicemente un messaggio, è il suo tipo di reso Unità
per impostazione predefinita. Unità
è un oggetto Kotlin (parleremo degli oggetti Kotlin nei post successivi) che è simile al vuoto
tipi in Java e C.
public object Unit override fun toString () = "kotlin.Unit"
Si noti che se non si dichiara esplicitamente il tipo di reso Unità
, il tipo è dedotto dal compilatore.
fun hello (name: String) // verrà ancora compilato print ("Hello $ name")
Le funzioni a linea singola oa linea singola sono funzioni che sono solo singole espressioni. In questa funzione, ci liberiamo delle parentesi graffe e usiamo il =
simbolo prima dell'espressione. In altre parole, ci liberiamo del blocco funzione.
fun calCircumference (raggio: Double): Double return (2 * Math.PI) * raggio
La funzione sopra può essere abbreviata in una singola riga:
fun calCircumference (radius: Double) = (2 * Math.PI) * raggio
Guardando la funzione aggiornata sopra, puoi vedere che abbiamo reso il nostro codice più conciso rimuovendo le parentesi graffe , il
ritorno
parola chiave, e anche il tipo di ritorno (che viene dedotto dal compilatore).
Puoi ancora includere il tipo di reso per essere più esplicito, se lo desideri.
fun calCircumference (raggio: Double): Double = (2 * Math.PI) * raggio
I parametri nominati consentono funzioni più leggibili nominando i parametri che vengono passati a una funzione quando vengono chiamati.
Nell'esempio seguente, abbiamo creato una funzione che stampa il mio nome completo.
fun sayMyFullName (firstName: String, lastName: String, middleName: String): Unit print ("Il mio nome completo è $ firstName $ middleName $ lastName");
Per eseguire la funzione sopra, la chiameremmo in questo modo:
sayMyFullName ("Chike", "Nnamdi", "Mgbemena")
Guardando la funzione chiamata sopra, non sappiamo quale Stringa
gli argomenti di tipo corrispondono a quali parametri di funzione (anche se alcuni IDE come IntelliJ IDEA possono aiutarci). Gli utenti della funzione dovranno esaminare la firma della funzione (o il codice sorgente) o la documentazione per sapere a cosa corrisponde ciascun parametro.
sayMyFullName (firstName = "Chike", middleName = "Nnamdi", lastName = "Mgbemena")
Nella seconda chiamata di funzione sopra, abbiamo fornito i nomi dei parametri prima dei valori degli argomenti. Puoi vedere che questa chiamata di funzione è più chiara e più leggibile della precedente. Questo modo di chiamare le funzioni aiuta a ridurre la possibilità di errori che possono accadere quando argomenti dello stesso tipo vengono scambiati per errore.
Il chiamante può anche alterare l'ordine dei parametri usando parametri con nome. Per esempio:
sayMyFullName (lastName = "Mgbemena", middleName = "Nnamdi", firstName = "Chike") // sarà ancora compilato
Nel codice sopra, abbiamo scambiato l'argomento posizione del nome di battesimo
con il cognome
. L'ordine degli argomenti non ha importanza con i parametri denominati perché il compilatore mapperà ciascuno di essi al parametro di funzione corretto.
In Kotlin, possiamo dare un valore predefinito di funzione per uno qualsiasi dei suoi parametri. Questi valori predefiniti vengono utilizzati se non viene assegnato nulla agli argomenti durante la chiamata della funzione. Per fare ciò in Java, dovremmo creare diversi metodi sovraccaricati.
Qui, nel nostro calCircumference ()
metodo, abbiamo modificato il metodo aggiungendo un valore predefinito per pi
parametro-Math.PI
, una costante dal java.lang.Math
pacchetto.
divertimento calCircumference (raggio: Double, pi: Double = Math.PI): Double = (2 * pi) * raggio
Quando chiamiamo questa funzione, possiamo o passare il nostro valore approssimativo per pi
o usare il valore predefinito.
print (calCircumference (24.0)) // valore predefinito utilizzato per PI e stampa 150.79644737231007 print (calCircumference (24.0, 3.14)) // valore passato per PI e stampa 150.72
Vediamo un altro esempio.
fun printName (firstName: String, middleName: String = "N / A", lastName: String) println ("nome: $ firstName - secondo nome: $ middleName - cognome: $ lastName")
Nel seguente codice, abbiamo provato a chiamare la funzione, ma non verrà compilata:
printName ("Chike", "Mgbemena") // non verrà compilato
Nella chiamata alla funzione sopra, sto passando il mio nome e cognome alla funzione, e spero di usare il valore predefinito per il secondo nome. Ma questo non verrà compilato perché il compilatore è confuso. Non sa a cosa serve l'argomento "Mgbemena": è per il secondo nome
o il cognome
parametro?
Per risolvere questo problema, possiamo combinare parametri con nome e parametri predefiniti.
printName ("Chike", lastName = "Mgbemena") // verrà ora compilato
Dato che Java non supporta i valori dei parametri predefiniti nei metodi, è necessario specificare tutti i valori dei parametri esplicitamente quando si chiama una funzione di Kotlin da Java. Ma Kotlin ci fornisce la funzionalità per rendere più semplice per i chiamanti Java annotando la funzione di Kotlin con @JvmOverloads
. Questa annotazione istruirà il compilatore Kotlin per generare le funzioni sovraccaricate Java per noi.
Nell'esempio seguente, abbiamo annotato il calCirumference ()
funzione con @JvmOverloads
.
@JvmScarica un divertimento divertenteCircuito (raggio: doppio, pi: doppio = Math.PI): doppio = (2 * pi) * raggio
Il codice seguente è stato generato dal compilatore Kotlin in modo che i chiamanti Java possano quindi scegliere quale chiamare.
// Java double calCircumference (double radius, double pi); doppia circonferenza (doppio raggio);
Nell'ultima definizione del metodo Java generato, il pi
parametro è stato omesso. Ciò significa che il metodo utilizzerà il valore predefinito pi
valore.
In Java, possiamo creare un metodo per ricevere un numero non specificato di argomenti includendo un'ellissi (...
) dopo un tipo nell'elenco dei parametri del metodo. Questo concetto è supportato anche dalle funzioni di Kotlin con l'uso di vararg
modificatore seguito dal nome del parametro.
fun printInts (vararg ints: Int): Unit for (n in ints) print ("$ n \ t") printInts (1, 2, 3, 4, 5, 6) // stampa 1 2 3 4 5 6
Il vararg
modificatore consente ai chiamanti di passare in un elenco di argomenti separati da virgole. Dietro le quinte, questo elenco di argomenti verrà inserito in un array.
Quando una funzione ha più parametri, il vararg
il parametro è in genere l'ultimo. È anche possibile avere parametri dopo il vararg
, ma dovrai usare parametri con nome per specificarli quando chiami la funzione.
fun printNumbers (myDouble: Double, myFloat: Float, vararg ints: Int) println (myDouble) println (myFloat) per (n in ints) print ("$ n \ t") printNumbers (1.34, 4.4F, 2, 3, 4, 5, 6) // verrà compilato
Ad esempio, nel codice sopra, il parametro con vararg
il modificatore si trova nell'ultima posizione in una lista di parametri multipli (questo è ciò che facciamo di solito). Ma cosa succede se non lo vogliamo nell'ultima posizione? Nell'esempio seguente, è nella seconda posizione.
fun printNumbers (myDouble: Double, vararg ints: Int, myFloat: Float) println (myDouble) println (myFloat) per (n in ints) print ("$ n \ t") printNumbers (1.34, 2, 3 , 4, 5, 6, myFloat = 4.4F) // compilerà printNumbers (1.34, ints = 2, 3, 4, 5, 6, myFloat = 4.4F) // non compilerà printNumbers (myDouble = 1.34, ints = 2, 3, 4, 5, 6, myFloat = 4.4F) // non verrà compilato
Come puoi osservare nel codice aggiornato sopra, abbiamo usato argomenti con nome sull'ultimo parametro per risolvere questo problema.
Diciamo che vogliamo passare una serie di numeri interi al nostro printNumbers ()
funzione. La funzione si aspetta che i valori vengano srotolati in una lista di parametri, comunque. Se si tenta di passare direttamente la matrice in printNumbers ()
, vedrai che non verrà compilato.
val intsArray: IntArray = intArrayOf (1, 3, 4, 5) printNumbers (1.34, intsArray, myFloat = 4.4F) // non verrà compilato
Per risolvere questo problema, dobbiamo usare l'operatore di diffusione *
. Questo operatore decomprimerà la matrice e quindi passerà i singoli elementi come argomenti nella funzione per noi.
val intsArray: IntArray = intArrayOf (1, 3, 4, 5) printNumbers (1.34, * intsArray, myFloat = 4.4F) // verrà ora compilato
Inserendo l'operatore di spread *
di fronte a intsArray
nella lista degli argomenti della funzione, il codice ora compila e produce lo stesso risultato come se avessimo passato gli elementi di intsArray
come elenco di argomenti separati da virgole.
A volte vogliamo restituire più valori da una funzione. Un modo è usare il Paio
digitare in Kotlin per creare un Paio
e poi restituirlo. Questo Paio
struttura racchiude due valori che possono essere successivamente accessibili. Questo tipo di Kotlin può accettare qualunque tipo tu fornisca il suo costruttore. E, inoltre, i due tipi non hanno nemmeno bisogno di essere lo stesso.
fun getUserNameAndState (id: Int): Pairrequire (id> 0, "Errore: id è minore di 0") val userNames: Map = mapOf (da 101 a "Chike", da 102 a "Segun", da 104 a "Jane") val userStates: Mappa = mapOf (da 101 a "Lagos", da 102 a "Imo", da 104 a "Enugu") val userName = userNames [id] val userState = userStates [id] return Pair (userName, userState)
Nella funzione sopra, abbiamo costruito un nuovo Paio
passando il nome utente
e UserState
variabili come primo e secondo argomento rispettivamente al suo costruttore, e quindi restituito questo Paio
al chiamante.
Un'altra cosa da notare è che abbiamo usato una funzione chiamata richiedere()
nel getUserNameAndState ()
funzione. Questa funzione di supporto dalla libreria standard viene utilizzata per dare ai nostri chiamanti funzioni una condizione preliminare per incontrarsi, oppure un IllegalArgumentException
sarà gettato (discuteremo di Eccezioni in Kotlin in un prossimo post). Il secondo argomento facoltativo a richiedere()
è una funzione letterale che restituisce un messaggio da visualizzare se viene generata un'eccezione. Ad esempio, chiamando il getUserNameAndState ()
funzione e passaggio -1
come argomento si innescherà:
Paio
val userNameAndStatePair: Pair= getUserNameAndState (101) println (userNameAndStatePair.first) // Chike println (userNameAndStatePair.second) // Lagos
Nel codice sopra, abbiamo avuto accesso al primo e al secondo valore dal Paio
digita usando il suo primo
e secondo
proprietà.
Tuttavia, c'è un modo migliore per farlo: la destrutturazione.
val (nome, stato) = getUserNameAndState (101) println (name) // Chike println (stato) // Lagos
Quello che abbiamo fatto nel codice aggiornato sopra è quello di assegnare direttamente il primo e il secondo valore del reso Paio
digita alle variabili nome
e stato
rispettivamente. Questa funzione è chiamata dichiarazione di destrutturazione.
Ora, cosa succede se si desidera restituire tre valori contemporaneamente? Kotlin ci fornisce un altro tipo utile chiamato Triplicare
.
fun getUserNameStateAndAge (id: Int): Triplerequire (id> 0, "id è minore di 0") val userNames: Map = mapOf (da 101 a "Chike", da 102 a "Segun", da 104 a "Jane") val userStates: Mappa = mapOf (da 101 a "Lagos", da 102 a "Imo", da 104 a "Enugu") val userName = userNames [id] val userState = userStates [id] val userAge = 6 return Triple (userNames [id], userStates [id ], userAge) val (nome, stato, età) = getUserNameStateAndAge (101) println (name) // Chike println (stato) // Lagos println (age) // 6
Sono sicuro che alcuni di voi si stanno chiedendo cosa fare se si desidera restituire più di tre valori. La risposta per questo sarà in un post successivo, quando discuteremo le classi di dati di Kotlin.
In questo tutorial, hai imparato a conoscere i pacchetti e le funzioni di base nel linguaggio di programmazione Kotlin. Nel prossimo tutorial della serie Kotlin From Scratch, imparerai di più sulle funzioni di Kotlin. A presto!
Per saperne di più sulla lingua di Kotlin, ti consiglio di visitare la documentazione di Kotlin. Oppure guarda alcuni dei nostri altri post di sviluppo di app per Android qui su Envato Tuts+!