Kotlin de la zero pachete și funcții de bază

Kotlin este un limbaj de programare modern care se compilează la Java bytecode. Este gratuit și open source, și promite să facă codificarea pentru Android chiar mai distractiv. 

În articolul precedent, ați aflat despre intervalele și colecțiile din Kotlin. În acest tutorial, vom continua să învățăm limba, urmărindu-ne cum să organizăm codul folosind pachetele și apoi să mergem la o introducere a funcțiilor din Kotlin.

1. Pachete

Dacă sunteți familiarizat cu Java, știți că Java utilizează pachete pentru a grupa clase conexe; de exemplu, java.util pachetul are un număr de clase utilitare utile. Pachetele sunt declarate cu pachet cuvânt cheie, și orice fișier Kotlin cu un pachet declarația de la început poate conține declarații de clase, funcții sau interfețe.

Declaraţie

Privind la codul de mai jos, am declarat un pachet com.chikekotlin.projectx folosind pachet cuvinte cheie. De asemenea, am declarat o clasă Clasa mea (vom discuta clasele din Kotlin în posturile viitoare) din acest pachet.

pachet com.chikekotlin.projectx clasa MyClass

Acum, numele complet calificat pentru clasă Clasa mea este com.chikekotlin.projectx.MyClass.

pachet com.chikekotlin.projectx distracție saySomething (): String retur "Cât de departe?" 

În codul de mai sus, am creat o funcție de nivel superior (vom ajunge la asta în scurt timp). Deci, la fel Clasa mea, numele complet calificat al funcției spune ceva() este com.chikekotlin.projectx.saySomething.

importurile

În Kotlin, folosim import declarație pentru a permite compilatorului să localizeze clasele, funcțiile, interfețele sau obiectele ce urmează a fi importate. În Java, pe de altă parte, nu putem importa direct funcții sau clase sau interfețe numai pentru metode. 

Folosim import pentru a accesa o funcție, o interfață, o clasă sau un obiect în afara pachetului unde a fost declarată. 

import com.chikekotlin.projectx.sayCeva distractiv principal (args: Array) saySomething () // va tipări "Cât de departe?" 

În fragmentul de cod de mai sus, am importat funcția spune ceva() dintr-un alt pachet, iar apoi am executat acea funcție.

Kotlin susține, de asemenea, importurile de metacaractere folosind * operator. Aceasta va importa toate clasele, interfețele și funcțiile declarate în pachet simultan. Acest lucru nu este recomandat, totuși, este de obicei mai bine să faceți importurile dvs. explicite.

import com.chikekotlin.projectx. *

Alinierea importului

Când aveți biblioteci care au nume de clasă sau funcții conflictuale (de exemplu, fiecare declară o funcție cu același nume), puteți utiliza la fel de pentru a da o entitate importată un nume temporar.

import com.chikekotlin.projectx.sayCeva import com.chikekotlin.projecty.sayCeva ca proiectYSaySomething distractiv principal (args: Array) projectYSaySomething ()

Rețineți că numele temporar este utilizat numai în fișierul în care a fost atribuit.

2. Funcții

O funcție grupează o serie de declarații de cod care execută o sarcină. Detaliile implementării funcției sunt ascunse de apelant.

În Kotlin, funcțiile sunt definite folosind distracţie cuvânt cheie, după cum se arată în următorul exemplu:

distracție salut (nume: String): String return "Hello $ name" val mesaj = hello ("Chike"

În codul de mai sus, am definit o funcție simplă Salut() cu un singur parametru Nume de tip Şir. Această funcție returnează a Şir tip. Formatul de definire a parametrilor pentru funcții este nume: tip, de exemplu. vârstă: Int, Preț: Dublă, student: StudentClass.

distracție hello (nume: String): unitate print ("Hello $ name") hello ("Chike") // va imprima "Hello Chike"

Funcția de mai sus este similară cu cea anterioară, însă observați că aceasta are un tip de returnare Unitate. Deoarece această funcție nu ne aduce nicio valoare semnificativă - imprimă doar un mesaj - tipul de retur este Unitate în mod implicit. Unitate este un obiect Kotlin (vom discuta obiecte Kotlin în posturi ulterioare) care este similar cu neavenit tipuri în Java și C.

obiect obiect public override fun toString () = "kotlin.Unit"

Rețineți că, dacă nu declarați în mod explicit tipul de returnare Unitate, tipul este dedus de compilator.

distracție salut (nume: String) // va compila în continuare imprimarea ("Hello $ name")

Funcții cu o singură linie

Funcțiile single-line sau one-line sunt funcții care sunt doar expresii singulare. În această funcție, scapăm de bretele și folosim = simbol înainte de expresie. Cu alte cuvinte, scapăm de blocul de funcții.

Distracție calCircumference (rază: Dublu): Dublă întoarcere (2 * Math.PI) * rază

Funcția de mai sus poate fi redusă într-o singură linie:

Distracție calCircumference (rază: Double) = (2 * Math.PI) * raza

Privind la funcția actualizată de mai sus, puteți vedea că am făcut codul nostru mai concis prin îndepărtarea bretelelor , întoarcere cuvântul cheie și, de asemenea, tipul de retur (care este dedus de compilator). 

Încă puteți include tipul de retur pentru a fi mai explicit dacă doriți.

distracție calCircumferință (rază: dublă): Dublă = (2 * Math.PI) * raza

Parametrii denumiți

Parametrii numiți permit funcții mai ușor de citit, prin denumirea parametrilor care sunt transmise unei funcții atunci când sunt apelate.

În următorul exemplu, am creat o funcție care imprimă numele meu complet.

distracție sayMyFullName (firstName: String, lastName: String, middleName: String): Unit print ("Numele meu complet este $ firstName $ middleName $ lastName"); 

Pentru a executa funcția de mai sus, am fi numit așa:

sayMyFullName ("Chike", "Nnamdi", "Mgbemena")

Privind la chemarea funcției de mai sus, nu știm ce Şir introduceți argumentele care corespund parametrilor funcției (deși unele IDE-uri precum IntelliJ IDEA ne pot ajuta). Utilizatorii funcției vor trebui să caute semnătura funcției (sau codul sursă) sau documentația pentru a ști ce corespund fiecărui parametru.

sayMyFullName (numeName = "Chike", middleName = "Nnamdi", lastName = "Mgbemena")

În al doilea apel de funcții de mai sus, am furnizat numele parametrilor înainte de valorile argumentului. Puteți vedea că această funcție este mai clară și mai lizibilă decât cea precedentă. Acest mod de apelare a funcțiilor ajută la reducerea posibilității de bug-uri care pot apărea atunci când argumentele de același tip sunt schimbate din greșeală.

Apelantul poate modifica, de asemenea, ordinea parametrilor utilizând parametrii numiți. De exemplu:

sayMyFullName (lastName = "Mgbemena", middleName = "Nnamdi", firstName = "Chike") // va compila încă

În codul de mai sus, am schimbat poziția argumentului Nume cu numele de familie. Ordinea argumentului nu contează cu parametrii numiți, deoarece compilatorul va cartografia fiecare dintre ele la parametrul funcției corecte.

Parametrii impliciți

În Kotlin, putem oferi o valoare implicită a funcției pentru oricare dintre parametrii săi. Aceste valori implicite sunt utilizate dacă nimic nu este atribuit argumentelor în timpul apelului funcției. Pentru a face acest lucru în Java, ar trebui să creați metode de încărcare diferite.

Aici, în nostru calCircumference () , am modificat metoda adăugând o valoare implicită pentru pi parametru-Math.PI, o constantă de la java.lang.Math pachet. 

Distracție calCircumferință (rază: Dublă, pi: Dublă = Math.PI): Dublă = (2 * pi) * raza

Când numim această funcție, putem trece valoarea noastră aproximată pi sau utilizați setarea implicită. 

print (calCircumference (24.0)) // valoarea implicită folosită pentru PI și tipărite 150.79644737231007 print (calCircumference (24.0, 3.14)) // valoarea trecută pentru PI și printuri 150.72

Să vedem un alt exemplu.

distracție printName (numeName: String, middleName: String = "N / A", lastName: String) println (nume: $ firstName - nume mijloc: $ middleName -

În următorul cod, am încercat să apelăm funcția, dar nu se va compila:

printName ("Chike", "Mgbemena") // nu se va compila

În apelul de funcții de mai sus, transmit numele și prenumele funcției și sperând să utilizez valoarea implicită pentru numele intermediar. Dar acest lucru nu se va compila deoarece compilatorul este confuz. Nu știe care este argumentul "Mgbemena" - este pentru al doilea nume sau numele de familie parametru? 

Pentru a rezolva această problemă, putem combina parametrii numiți și parametrii impliciți. 

printName ("Chike", lastName = "Mgbemena") // se va compila acum

Interoperabilitate Java

Dat fiind că Java nu suportă valori de parametru implicite în metode, va trebui să specificați explicit toate valorile parametrilor atunci când apelați o funcție Kotlin din Java. Dar Kotlin ne oferă funcționalitatea pentru a facilita apelanții Java prin adnotarea funcției Kotlin @JvmOverloads. Această adnotare va instrui compilatorul Kotlin să genereze funcțiile Java supraîncărcate pentru noi.

În următorul exemplu, am adnotat calCirumference () funcția cu @JvmOverloads.

@ JvmOverloads distracție calCircumference (rază: Dublă, pi: Dublă = Math.PI): Dublă = (2 * pi) * raza

Următorul cod a fost generat de compilatorul Kotlin, astfel încât apelanții Java pot alege apoi pe cine să sune.

// Java double calCircumference (raza dublă, dublă pi); dublu calCircumferință (rază dublă);

În ultima definiție a metodei Java generată, pi parametru a fost omis. Aceasta înseamnă că metoda va utiliza valoarea implicită pi valoare.

Argumente nelimitate

În Java, putem crea o metodă pentru a primi un număr nespecificat de argumente prin includerea unei elipse (... ) după un tip din lista de parametri a metodei. Acest concept este, de asemenea, susținut de funcțiile Kotlin cu utilizarea vararg modificator urmat de numele parametrului.

Funcții de tipărire fun (vararg ints: Int): Unitatea pentru (n in t) print ("$ n \ t") printInts (1, 2, 3, 4, 5, 6) 4 5 6

 vararg Modificatorul permite apelanților să treacă printr-o listă de argumente separate prin virgulă. În spatele scenei, această listă de argumente va fi înfășurată într-o matrice. 

Atunci când o funcție are mai mulți parametri, vararg parametrul este de obicei ultimul. De asemenea, este posibil să existe parametri după vararg, dar va trebui să utilizați parametri numiți pentru a le specifica atunci când apelați funcția. 

distracție printNumbers (myDouble: Double, myFloat: Float, vararg ints: Int) println (myDouble) println (myFloat) pentru n ints) print (" 2, 3, 4, 5, 6) // va compila

De exemplu, în codul de mai sus, parametrul cu vararg Modificatorul se află în ultima poziție într-o listă de parametri multiple (aceasta este ceea ce facem de obicei). Dar dacă nu o dorim în ultima poziție? În exemplul următor, se află în a doua poziție.

Distribuitorul (myDouble: Double, vararg ints: Int, myFloat: Float) println (myDouble) println (myFloat) pentru n in ints) print ("$ n \ t") printNumbers (1.34, 2, 3 , 4, 5, 6, myFloat = 4.4F) // va compila PrintNumbers (1.34, ints = 2, 3, 4, 5, 6, myFloat = 4.4F) // nu va compila PrintNumbers (myDouble = 2, 3, 4, 5, 6, myFloat = 4.4F) // nu se va compila, de asemenea

După cum puteți observa în codul actualizat de mai sus, am folosit argumente numite pe ultimul parametru pentru a rezolva acest lucru.

Spread Operator

Să presupunem că vrem să trecem o serie de numere întregi printNumbers () funcţie. Funcția așteaptă însă ca valorile să fie derulate într-o listă de parametri. Dacă încercați să treceți direct matricea printNumbers (), veți vedea că nu se va compila. 

val intArray: IntArray = intArrayOf (1, 3, 4, 5) printNumbers (1.34, intsArray, myFloat = 4.4F) // nu compila

Pentru a rezolva această problemă, trebuie să folosim operatorul de răspândire *. Acest operator va despacheta matricea și apoi va transmite elementele individuale ca argumente în funcția pentru noi. 

val intarsArray: IntArray = intArrayOf (1, 3, 4, 5) printNumbers (1.34, * intsArray, myFloat = 4.4F) // va compila acum

Introducerea operatorului de distribuire * în fața intsArray în lista de argumente a funcției, codul se compilează acum și produce același rezultat ca și cum am fi trecut elementele lui intsArray ca o listă de argumente separate prin virgulă. 

Returnați mai multe valori

Uneori vrem să returnăm mai multe valori dintr-o funcție. O modalitate este de a utiliza Pereche tip în Kotlin pentru a crea un Pereche și apoi returnați-o. Acest Pereche structura cuprinde două valori care pot fi accesate mai târziu. Acest tip Kotlin poate accepta toate tipurile pe care le furnizați constructorului. Și, mai mult, cele două tipuri nu trebuie nici măcar să fie la fel. 

distracție getUserNameAndState (id: Int): Pereche necesită (id> 0, "Eroare: id este mai mică de 0") val userNames: Map = mapOf (101 la "Chike", 102 la "Segun", 104 la "Jane") val userStates: Harta = mapOf (101 la "Lagos", 102 la "Imo", 104 la "Enugu") val userName = userNames [id] val userState = userStates [id] retur Pair (userName, userState)

În funcția de mai sus, am construit un nou Pereche prin trecerea lui nume de utilizator și userState variabilele ca primul și respectiv al doilea argument pentru constructorul său, apoi au returnat acest lucru Pereche la apelant.

Un alt lucru de observat este că am folosit o funcție numită require () în getUserNameAndState () funcţie. Această funcție de ajutor din biblioteca standard este utilizată pentru a oferi apelanților noștri funcția o condiție prealabilă pentru a satisface, sau altceva IllegalArgumentException vor fi aruncate (vom discuta Excepții în Kotlin într-un post viitor). Al doilea argument opțional la require () este o funcție literală care returnează un mesaj care va fi afișat dacă excepția este aruncată. De exemplu, sunând la getUserNameAndState () funcționare și trecere -1 ca un argument pentru aceasta va declanșa:

 

Preluarea datelor din Pereche

val userNameAndStatePair: Pereche = getUserNameAndState (101) println (userNameAndStatePair.first) // Chineză println (userNameAndStatePair.second) // Lagos

În codul de mai sus, am accesat prima și a doua valoare din Pereche tip folosind primul și al doilea proprietăţi.

Cu toate acestea, există o modalitate mai bună de a face acest lucru: distrugerea.

val (nume, stare) = getUserNameAndState (101) println (nume) // Chike println (state) // Lagos

Ceea ce am făcut în codul actualizat de mai sus este atribuirea directă a primei și celei de-a doua valori a metodei returnate Pereche tip la variabile Nume și stat respectiv. Această caracteristică este numită declarație de distrugere.

Valori Triple Return și dincolo

Acum, dacă doriți să reveniți la trei valori simultan? Kotlin ne oferă un alt tip util numit Triplu.

distracție getUserNameStateAndAge (id: Int): Triplă necesită (id> 0, "id este mai mică de 0") val userNames: Map = mapOf (101 la "Chike", 102 la "Segun", 104 la "Jane") val userStates: Harta = mapOf (101 la "Lagos", 102 la "Imo", 104 la "Enugu") val userName = userNames [id] val userState = userStates [id] val userAge = ], valA (nume, stare, vârstă) = getUserNameStateAndAge (101) println (nume) // Chike println (state) // Lagos println (vârstă) // 6

Sunt sigur că unii dintre voi vă întrebați ce să faceți dacă doriți să reveniți la mai mult de trei valori. Răspunsul pentru acest lucru va fi într-un post mai târziu, când discutăm clasele de date ale lui Kotlin.

Concluzie

În acest tutorial, ați aflat despre pachetele și funcțiile de bază din limba de programare Kotlin. În următorul tutorial din seria Kotlin From Scratch, veți afla mai multe despre funcțiile din Kotlin. Ne vedem în curând!

Pentru a afla mai multe despre limba Kotlin, vă recomand să vizitați documentația Kotlin. Sau verificați câteva dintre celelalte postări pentru dezvoltarea aplicațiilor Android aici pe Envato Tuts+!

Cod