Uvod u jezik Kotlin

1. Pregled

U ovom uputstvu ćemo pogledati Kotlin, novi jezik u JVM svijetu, i neke od njegovih osnovnih značajki, uključujući klase, nasljeđivanje, uvjetne izjave i konstrukcije petlje.

Zatim ćemo pogledati neke od glavnih značajki koje Kotlin čine atraktivnim jezikom, uključujući null sigurnost, klase podataka, funkcije proširenja i Niz predlošci.

2. Ovisnosti Mavena

Da biste koristili Kotlin u svom projektu Maven, morate dodati standardnu ​​biblioteku Kotlin u svoj pom.xml:

 org.jetbrains.kotlin kotlin-stdlib 1.0.4 

Da biste dodali JUnit podršku za Kotlin, trebat ćete uključiti i sljedeće ovisnosti:

 org.jetbrains.kotlin kotlin-test-junit 1.0.4 test junit junit 4.12 test 

Najnovije verzije kotlin-stdlib, kotlin-test-junit i junit možete pronaći na Maven Central.

Konačno, morat ćete konfigurirati izvorne direktorije i dodatak Kotlin da biste izvršili izgradnju Mavena:

 $ {project.basedir} / src / main / kotlin $ {project.basedir} / src / test / kotlin kotlin-maven-plugin org.jetbrains.kotlin 1.0.4 compile compile test-compile test-compile 

Najnoviju verziju kotlin-maven-plugin možete pronaći u Maven Central.

3. Osnovna sintaksa

Pogledajmo osnovne blokove Kotlin jezika.

Postoji određena sličnost s Javom (npr. Definiranje paketa je na isti način). Pogledajmo razlike.

3.1. Definiranje funkcija

Definirajmo funkciju koja ima dva Int parametra sa Int tip povrata:

zabavna suma (a: Int, b: Int): Int {return a + b}

3.2. Definiranje lokalnih varijabli

Jednom dodijeli (samo za čitanje) lokalnu varijablu:

val a: Int = 1 val b = 1 val c: Int c = 1

Imajte na umu tu vrstu varijable b zaključuje Kotlinov kompajler. Također bismo mogli definirati promjenjive varijable:

var x = 5 x + = 1

4. Neobvezna polja

Kotlin ima osnovnu sintaksu za definiranje polja koje bi moglo biti poništeno (neobavezno). Kada želimo proglasiti da je vrsta polja poništavajuća, trebamo koristiti tip sufiksiran upitnikom:

val email: Niz?

Kada ste definirali nullable polje, potpuno je valjano dodijeliti null tome:

val email: Niz? = null

To znači da bi u polju e-pošte mogao biti null. Ako ćemo napisati:

val email: String = "vrijednost"

Tada trebamo dodijeliti vrijednost polju e-pošte u istoj izjavi koju deklariramo e-poštom. Ne može imati null vrijednost. Vratit ćemo se u Kotlin null sigurnost u kasnijem odjeljku.

5. Nastava

Pokažimo kako stvoriti jednostavnu klasu za upravljanje određenom kategorijom proizvoda. Naše Upravitelj predmeta klasa u nastavku ima zadani konstruktor koji popunjava dva polja - kategorijaId i dbConnection - i neobavezno e-mail polje:

class ItemManager (val categoryId: String, val dbConnection: String) {var email = "" // ...}

Da Upravitelj predmeta (...) konstrukt stvara konstruktor i dva polja u našoj klasi: kategorijaId i dbConnection

Imajte na umu da naš konstruktor koristi val ključna riječ za svoje argumente - to znači da će odgovarajuća polja biti konačni i nepromjenjiv. Da smo koristili var ključna riječ (kao što smo to učinili prilikom definiranja e-mail polje), tada bi ta polja bila promjenjiva.

Stvorimo instancu ItemManager koristeći zadani konstruktor:

ItemManager ("cat_id", "db: // connection")

Mogli bismo konstruirati Upravitelj predmeta pomoću imenovanih parametara. Vrlo je korisno kada imate kao u ovom primjeru funkciju koja uzima dva parametra istog tipa, npr. Niz, a vi ne želite zbuniti njihov redoslijed. Pomoću parametara imenovanja možete izričito napisati koji je parametar dodijeljen. U klasi Upravitelj predmeta postoje dva polja, kategorijaId i dbConnection pa se na oba može uputiti pomoću imenovanih parametara:

ItemManager (categoryId = "catId", dbConnection = "db: // Connection")

Vrlo je korisno kada funkciji moramo proslijediti više argumenata.

Ako su vam potrebni dodatni konstruktori, definirali biste ih pomoću konstruktor ključna riječ. Definirajmo još jedan konstruktor koji također postavlja e-mail polje:

konstruktor (categoryId: String, dbConnection: String, email: String): this (categoryId, dbConnection) {this.email = email}

Imajte na umu da ovaj konstruktor poziva zadani konstruktor koji smo definirali gore prije postavljanja polja e-pošte. A budući da smo već definirali kategorijaId i dbConnection biti nepromjenjiv pomoću val u zadanom konstruktoru, ne trebamo ponavljati val ključna riječ u dodatnom konstruktoru.

Sada, kreirajmo instancu pomoću dodatnog konstruktora:

ItemManager ("cat_id", "db: // connection", "[email protected]")

Ako želite definirati metodu instance na Upravitelj predmeta, to biste učinili pomoću zabava ključna riječ:

zabava je izSpecificCategory (catId: String): Boolean {return categoryId == catId}

6. Nasljeđivanje

Prema zadanim postavkama, Kotlinove su klase zatvorene za produženje - što je ekvivalent klasi označenoj konačni na Javi.

Da biste odredili da je klasa otvorena za proširenje, koristili biste otvorena ključna riječ prilikom definiranja klase.

Definirajmo Artikal razred koji je otvoren za produženje:

stavka otvorene klase (val id: String, val ime: String = "unknown_name") {open fun getIdOfItem (): String {return id}}

Imajte na umu da smo također označili getIdOfItem () metoda kao otvorena. To omogućuje nadjačavanje.

Sada, produžimo Artikal klase i nadjačati getIdOfItem () metoda:

class ItemWithCategory (id: String, name: String, val categoryId: String): Item (id, name) {override fun getIdOfItem (): String {return id + name}}

7. Uvjetne izjave

U Kotlinu, uvjetna izjava ako je ekvivalent funkcije koja vraća neku vrijednost. Pogledajmo primjer:

zabavno makeAnalyisOfCategory (catId: String): Jedinica {val result = if (catId == "100") "Yes" else "No" println (result)}

U ovom primjeru vidimo da ako mačka je jednako "100" uvjetni blok vraća "Da", inače vraća "Ne". Vraćena vrijednost dodjeljuje se proizlaziti.

Mogli biste stvoriti normalnu akodrugo blok:

val broj = 2 if (broj 10) {println ("broj je veći od 10")}

Kotlin ima i vrlo koristan kada naredba koja djeluje poput napredne naredbe prebacivanja:

val name = "John" when (name) {"John" -> println ("Hi man") "Alice" -> println ("Hi lady")} 

8. Zbirke

U Kotlinu postoje dvije vrste kolekcija: promjenjiva i nepromjenjiva. Kada kreiramo nepromjenjivu zbirku, to znači da je samo za čitanje:

val stavke = listOf (1, 2, 3, 4)

Na tom popisu nema elementa za dodavanje funkcije.

Kada želimo stvoriti promjenjivi popis koji bi se mogao izmijeniti, trebamo koristiti mutableListOf () metoda:

val rwList = mutableListOf (1, 2, 3) rwList.add (5)

Promjenjiv popis ima dodati() metodu kako bismo joj mogli dodati element. Postoje i metode jednake ostalim vrstama kolekcija: mutableMapOf (), mapOf (), setOf (), mutableSetOf ()

9. Iznimke

Mehanizam rukovanja iznimkama vrlo je sličan onom u Javi.

Sve se klase iznimki proširuju Bacljivo. Iznimka mora imati poruku, stacktrace i neobavezni uzrok. Svaka iznimka u Kotlinu nije označena, što znači da nas kompajler ne prisiljava da ih uhvatimo.

Da bismo izbacili objekt iznimke, trebamo upotrijebiti bacanje-izraz:

throw Exception ("msg")

Obrada iznimke vrši se pomoću probaj ... catch block (konačno nije obavezno):

pokušajte {} uhvatiti (e: SomeException) {} napokon {}

10. Lambda

U Kotlinu bismo mogli definirati lambda funkcije i proslijediti ih kao argumente drugim funkcijama.

Pogledajmo kako definirati jednostavnu lambda:

val sumLambda = {a: Int, b: Int -> a + b}

Mi smo definirali sumLambda funkcija koja uzima dva argumenta tipa Int kao argument i vraća se Int.

Mogli bismo proći lambdu uokolo:

@Test zabava givenListOfNumber_whenDoingOperationsUsingLambda_shouldReturnProperResult () {// data val listOfNumbers = listOf (1, 2, 3) // when val sum = listOfNumbers.reduce {a, b -> a + b} // then sumrtEquals (6, sumrtEquals (6, sumrt)

11. Looping konstrukcije

U Kotlinu se pregledavanje kolekcija moglo obaviti pomoću standarda za..u konstruirati:

brojevi val = arrayOf ("prvi", "drugi", "treći", "četvrti")
za (n u brojkama) {println (n)}

Ako želimo ponavljati niz čitavih brojeva, mogli bismo koristiti konstrukciju raspona:

za (i u 2..9, korak 2) {println (i)}

Imajte na umu da je raspon u gornjem primjeru obuhvaćajući s obje strane. The korak parametar nije obavezan i ekvivalentan je dvostrukom povećanju brojača u svakoj iteraciji. Izlaz će biti sljedeći:

2 4 6 8

Mogli bismo koristiti rangeTo () funkcija koja je definirana na Int razred na sljedeći način:

1.rangeTo (10) .map {it * 2}

Rezultat će sadržavati (imajte na umu da rangeTo () također uključuje):

[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

12. Nulta sigurnost

Pogledajmo jednu od ključnih značajki Kotlina - nultu sigurnost koja je ugrađena u jezik. Da bismo ilustrirali zašto je ovo korisno, stvorit ćemo jednostavnu uslugu koja vraća Artikal objekt:

class ItemService {fun findItemNameForId (id: String): Predmet? {val itemId = UUID.randomUUID (). toString () return Item (itemId, "name- $ itemId"); }}

Važno je primijetiti vraćeni tip te metode. To je objekt iza kojeg slijedi upitnik. To je konstrukcija iz jezika Kotlin, što znači da Artikal vraćeno iz te metode moglo bi biti null. Moramo riješiti taj slučaj u vrijeme kompajliranja, odlučujući što želimo učiniti s tim objektom (više je ili manje ekvivalentan Javi 8 Neobvezno tip).

Ako potpis metode ima tip bez upitnika:

zabavno findItemNameForId (id: String): Stavka

tada pozivni kod neće trebati obrađivati ​​null slučaj, jer ga jamče kompajler i jezik Kotlin, da vraćeni objekt ne može biti null.

Inače, ako postoji nullable objekt koji se prosljeđuje metodi, a taj se slučaj ne obrađuje, neće se prevesti.

Napišimo test za sigurnost tipa Kotlin:

val id = "item_id" val itemService = ItemService () val rezultat = itemService.findItemNameForId (id) assertNotNull (rezultat? .let {it -> it.id}) assertNotNull (rezultat !!. id) 

Ovdje vidimo da je nakon izvršavanja metode findItemNameForId (), vraćeni tip je Kotlin Ništav. Da biste pristupili polju tog objekta (iskaznica), taj slučaj moramo riješiti u vrijeme sastavljanja. Metoda neka () izvršit će se samo ako rezultat nije poništavan. Jad Polju se može pristupiti unutar lambda funkcije jer je nula sigurno.

Drugi način za pristup tom poništenom polju objekta je upotreba operatora Kotlin !!. Ekvivalentno je:

if (rezultat == null) {throwNpe (); } vratiti rezultat;

Kotlin će provjeriti je li taj objekt null ako je tako, bacit će a NullPointerException, u protivnom će vratiti odgovarajući objekt. Funkcija throwNpe () je unutarnja funkcija Kotlina.

13. Klase podataka

Vrlo lijepa jezična konstrukcija koja se može naći u Kotlinu su klase podataka (ekvivalent je "klasi slučaja" iz jezika Scala). Svrha takvih klasa je zadržavanje samo podataka. U našem primjeru imali smo Artikal klasa koja sadrži samo podatke:

Stavka podatkovne klase (val id: String, val ime: String)

Kompajler će za nas stvoriti metode hashCode (), jednako (), i toString (). Dobra je praksa učiniti klase podataka nepromjenjivim pomoću a val ključna riječ. Klase podataka mogu imati zadane vrijednosti polja:

Stavka podatkovne klase (val id: String, ime val: String = "unknown_name")

To vidimo Ime polje ima zadanu vrijednost "nepoznato_ime".

14. Funkcije produžetka

Pretpostavimo da imamo razred koji je dio biblioteke treće strane, ali želimo ga proširiti dodatnom metodom. Kotlin nam omogućuje da to učinimo pomoću funkcija proširenja.

Razmotrimo primjer u kojem imamo popis elemenata i želimo uzeti slučajni element s tog popisa. Želimo dodati novu funkciju slučajno () trećoj strani Popis razred.

Evo kako to izgleda u Kotlinu:

zabavna lista.random (): T? {if (this.isEmpty ()) return null return get (ThreadLocalRandom.current (). nextInt (count ()))}

Ovdje je najvažnije primijetiti potpis metode. Metoda ima prefiks s imenom klase u koju dodajemo ovu dodatnu metodu.

Unutar metode produženja djelujemo na opsegu popisa, dakle koristeći ovaj dao pristup korištenju metoda instanci popisa poput prazno je() ili računati(). Tada smo u mogućnosti nazvati slučajno () metoda na bilo kojem popisu koji je u tom opsegu:

zabava getRandomElementOfList (popis: Popis): T? {povratak list.random ()}

Stvorili smo metodu koja uzima popis, a zatim izvršava funkciju prilagođenog proširenja slučajno () to je prethodno bilo definirano. Napišimo test za našu novu funkciju:

elementi val = listOf ("a", "b", "c") val rezultat = ListExtension (). getRandomElementOfList (elementi) assertTrue (elements.contains (rezultat)) 

Mogućnost definiranja funkcija koje „proširuju“ klase trećih strana vrlo je moćna značajka i naš kôd može učiniti sažetijim i čitljivijim.

15. Predlošci žica

Vrlo lijepa značajka jezika Kotlin je mogućnost korištenja predložaka za Nizs. Vrlo je korisno jer ne trebamo spajati Nizs ručno:

val firstName = "Tom" val secondName = "Mary" val concatOfNames = "$ firstName + $ secondName" val sum = "four: $ {2 + 2}" 

Također možemo procijeniti izraz unutar ${} blok:

val itemManager = ItemManager ("cat_id", "db: // connection") val rezultat = "rezultat funkcije: $ {itemManager.isFromSpecificCategory (" 1 ")}"

16. Kotlin / Java interoperabilnost

Kotlin - Java interoperabilnost je jednostavno. Pretpostavimo da imamo Java klasu s metodom koja djeluje Niz:

klasa StringUtils {javni statički String toUpperCase (naziv niza) {return name.toUpperCase (); }}

Sada želimo izvršiti taj kod iz naše klase Kotlin. Trebamo samo uvesti tu klasu i bez problema bismo mogli izvršiti java metodu iz Kotlina:

val name = "tom" val res = StringUtils.toUpperCase (name) assertEquals (res, "TOM")

Kao što vidimo, koristili smo java metodu iz Kotlin koda.

Pozivanje Kotlin koda s Jave također je vrlo jednostavno. Definirajmo jednostavnu funkciju Kotlina:

razred MathematicsOperations {zabava addTwoNumbers (a: Int, b: Int): Int {return a + b}}

Izvršenje addTwoNumbers () iz Java koda vrlo je jednostavno:

int res = new MathematicsOperations (). addTwoNumbers (2, 4); assertEquals (6, res);

Vidimo da nam je poziv na Kotlinov kod bio transparentan.

Kada definiramo metodu u javi, taj tip povrata je poništiti, u Kotlinu će vraćena vrijednost biti a Jedinica tip.

U jeziku Java postoje neki posebni identifikatori ( je, objekt, u, ..) da ih treba izbjeći kada se koriste u kodu Kotlin. Na primjer, mogli bismo definirati metodu koja ima naziv objekt() ali moramo zapamtiti da pobjegnemo tom imenu jer je ovo poseban identifikator u javi:

zabava `object` (): Niz {return" ovo je objekt "}

Tada bismo mogli izvršiti tu metodu:

`objekt` ()

17. Zaključak

Ovaj članak predstavlja uvod u jezik Kotlin i njegove ključne značajke. Počinje uvođenjem jednostavnih pojmova poput petlji, uvjetnih izraza i definiranjem klasa. Zatim prikazuje neke naprednije značajke kao što su funkcije proširenja i nulta sigurnost.

Provedbu svih ovih primjera i isječaka koda možete pronaći u projektu GitHub.