Kotlin From Scratch pacchetti e funzioni di base

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.

1. Pacchetti

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.

Dichiarazione

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.

importazioni

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. *

Alias ​​di importazione

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.

2. Funzioni

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")

Funzioni a linea singola

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

Parametri nominati

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.

Parametri predefiniti

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

Interoperabilità Java

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.

Argomenti illimitati

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.

Spread Operator

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. 

Restituisce più valori

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): Pair require (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à:

 

Recupero dei dati da 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.

Valori di ritorno tripli e oltre

Ora, cosa succede se si desidera restituire tre valori contemporaneamente? Kotlin ci fornisce un altro tipo utile chiamato Triplicare.

fun getUserNameStateAndAge (id: Int): Triple require (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.

Conclusione

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+!