Introduktion til Kotlin-sproget

1. Oversigt

I denne vejledning skal vi se på Kotlin, et nyt sprog i JVM-verdenen, og nogle af dens grundlæggende funktioner, herunder klasser, arv, betingede udsagn og looping-konstruktioner.

Derefter vil vi se på nogle af de vigtigste funktioner, der gør Kotlin til et attraktivt sprog, herunder null sikkerhed, dataklasser, udvidelsesfunktioner og Snor skabeloner.

2. Maven-afhængigheder

For at bruge Kotlin i dit Maven-projekt skal du tilføje Kotlin-standardbiblioteket til dit pom.xml:

 org.jetbrains.kotlin kotlin-stdlib 1.0.4 

For at tilføje JUnit-support til Kotlin skal du også medtage følgende afhængigheder:

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

Du kan finde de nyeste versioner af kotlin-stdlib, kotlin-test-junit og junit på Maven Central.

Endelig skal du konfigurere kildekatalogerne og Kotlin-plugin'et for at udføre en Maven-build:

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

Du kan finde den nyeste version af kotlin-maven-plugin i Maven Central.

3. Grundlæggende syntaks

Lad os se på grundlæggende byggesten i Kotlin Language.

Der er en vis lighed med Java (f.eks. Definerer pakker er på samme måde). Lad os se på forskelle.

3.1. Definition af funktioner

Lad os definere en funktion, der har to Int-parametre med Int returtype:

sjov sum (a: Int, b: Int): Int {returner + +}

3.2. Definition af lokale variabler

Tildel én gang (skrivebeskyttet) lokal variabel:

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

Bemærk den type variabel b udledes af en Kotlin-kompilator. Vi kunne også definere mutable variabler:

var x = 5 x + = 1

4. Valgfri felter

Kotlin har grundlæggende syntaks til at definere et felt, der kan være ugyldigt (valgfrit). Når vi vil erklære, at denne type felt er ugyldig, er vi nødt til at bruge typen efterfulgt af et spørgsmålstegn:

val email: String?

Når du definerede et ugyldigt felt, er det helt gyldigt at tildele en nul til det:

val email: String? = null

Det betyder, at i et e-mail-felt kunne være en nul. Hvis vi skriver:

val email: String = "værdi"

Derefter skal vi tildele en værdi til e-mail-feltet i den samme erklæring, som vi erklærer e-mail. Det kan ikke have en nulværdi. Vi vender tilbage til Kotlin nul sikkerhed i et senere afsnit.

5. Klasser

Lad os demonstrere, hvordan man opretter en simpel klasse til styring af en bestemt kategori af et produkt. Vores ItemManager klasse nedenfor har en standardkonstruktør, der udfylder to felter - categoryId og dbTilslutning - og en valgfri e-mail Mark:

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

At ItemManager (…) konstruktion skaber konstruktør og to felter i vores klasse: categoryId og dbTilslutning

Bemærk, at vores konstruktør bruger val nøgleord for dets argumenter - det betyder, at de tilsvarende felter vil være endelig og uforanderlig. Hvis vi havde brugt var nøgleord (som vi gjorde, da vi definerede e-mail felt), så ville disse felter blive ændret.

Lad os oprette en forekomst af ItemManager ved hjælp af standardkonstruktøren:

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

Vi kunne konstruere ItemManager ved hjælp af navngivne parametre. Det er meget nyttigt, når du har som i dette eksempel funktion, der tager to parametre med samme type, f.eks. Snor, og du vil ikke forveksle en ordre af dem. Ved hjælp af navngivningsparametre kan du eksplicit skrive, hvilken parameter der er tildelt. I klassen ItemManager der er to felter, categoryId og dbTilslutning så begge kan henvises til ved hjælp af navngivne parametre:

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

Det er meget nyttigt, når vi skal overføre flere argumenter til en funktion.

Hvis du har brug for yderligere konstruktører, ville du definere dem ved hjælp af konstruktør nøgleord. Lad os definere en anden konstruktør, der også indstiller e-mail Mark:

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

Bemærk! Og da vi allerede definerede categoryId og dbTilslutning at være uforanderlig ved hjælp af val nøgleord i standardkonstruktøren, behøver vi ikke gentage val nøgleord i den ekstra konstruktør.

Lad os nu oprette en instans ved hjælp af den ekstra konstruktør:

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

Hvis du vil definere en instansmetode til ItemManager, ville du gøre det ved hjælp af sjovt nøgleord:

fun isFromSpecificCategory (catId: String): Boolean {return categoryId == catId}

6. Arv

Som standard er Kotlins klasser lukket for forlængelse - svarende til en markeret klasse endelig i Java.

For at specificere, at en klasse er åben for udvidelse, skal du bruge åben nøgleord, når du definerer klassen.

Lad os definere en Vare klasse, der er åben for udvidelse:

open class Item (val id: String, val name: String = "unknown_name") {open fun getIdOfItem (): String {return id}}

Bemærk, at vi også betegnede getIdOfItem () metode som åben. Dette gør det muligt at tilsidesætte det.

Lad os nu udvide Vare klasse og tilsidesætte getIdOfItem () metode:

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

7. Betingede erklæringer

I Kotlin, betinget erklæring hvis svarer til en funktion, der returnerer en værdi. Lad os se på et eksempel:

sjov makeAnalyisOfCategory (catId: String): Enhed {val resultat = hvis (catId == "100") "Ja" ellers "Nej" println (resultat)}

I dette eksempel ser vi, at hvis katId er lig med "100" betinget blok returnerer "Ja" ellers returnerer det "Nej". Returneret værdi tildeles resultat.

Du kan oprette en normal hvisandet blok:

val nummer = 2 hvis (nummer 10) {println ("antallet er større end 10")}

Kotlin har også en meget nyttig hvornår kommando, der fungerer som en avanceret switch-sætning:

val name = "John" når (navn) {"John" -> println ("Hej mand") "Alice" -> println ("Hej dame")} 

8. Samlinger

Der er to typer samlinger i Kotlin: mutable og immutable. Når vi opretter en uforanderlig samling, betyder det, at den kun er læst:

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

Der er ikke noget tilføjelseselement på denne liste.

Når vi vil oprette en ændret liste, der kan ændres, skal vi bruge den mutableListOf () metode:

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

En ændret liste har tilføje() metode, så vi kunne tilføje et element til det. Der er også tilsvarende metode som andre typer samlinger: mutableMapOf (), mapOf (), setOf (), mutableSetOf ()

9. Undtagelser

Mekanismen for undtagelseshåndtering er meget lig den i Java.

Alle undtagelsesklasser udvides Kan kastes. Undtagelsen skal have en besked, stacktrace og en valgfri årsag. Hver undtagelse i Kotlin er ikke markeret, hvilket betyder, at kompilatoren ikke tvinger os til at fange dem.

For at kaste et undtagelsesobjekt skal vi bruge kasteudtrykket:

kast undtagelse ("msg")

Håndtering af undtagelser sker ved hjælp af prøv ... fang blok (endelig valgfri):

prøv {} catch (e: SomeException) {} endelig {}

10. Lambdas

I Kotlin kunne vi definere lambdafunktioner og videregive dem som argumenter til andre funktioner.

Lad os se, hvordan man definerer en simpel lambda:

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

Vi definerede sumLambda funktion, der tager to argumenter af typen Int som et argument og vender tilbage Int.

Vi kunne passere en lambda rundt:

@Test fun givenListOfNumber_whenDoingOperationsUsingLambda_shouldReturnProperResult () {// given val listOfNumbers = listOf (1, 2, 3) // when val sum = listOfNumbers.reduce {a, b -> a + b} // then assertEquals (6, sum)}

11. Looping-konstruktioner

I Kotlin kunne man gennemgå en samling gennem en standard for..in konstruere:

valnumre = arrayOf ("første", "anden", "tredje", "fjerde")
for (n i tal) {println (n)}

Hvis vi vil gentage en række heltal, kan vi bruge en rækkekonstruktion:

for (i i 2..9 trin 2) {println (i)}

Bemærk, at rækkevidden i eksemplet ovenfor inkluderer begge sider. Det trin parameter er valgfri, og det svarer til at øge tælleren to gange i hver iteration. Outputtet følger:

2 4 6 8

Vi kunne bruge en rækkevidde til () funktion, der er defineret på Int klasse på følgende måde:

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

Resultatet vil indeholde (bemærk det rækkevidde til () er også inkluderende):

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

12. Null sikkerhed

Lad os se på et af nøglefunktionerne i Kotlin - nul sikkerhed, der er indbygget i sproget. For at illustrere, hvorfor dette er nyttigt, opretter vi en simpel tjeneste, der returnerer en Vare objekt:

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

Det vigtige at bemærke er returneret type af denne metode. Det er et objekt efterfulgt af spørgsmålstegnet. Det er en konstruktion fra Kotlin-sprog, hvilket betyder det Vare returneret fra denne metode kunne være nul. Vi er nødt til at håndtere sagen på kompileringstidspunktet og beslutte, hvad vi vil gøre med det objekt (det svarer mere eller mindre til Java 8 Valgfri type).

Hvis metodesignaturen har typen uden spørgsmålstegn:

fun findItemNameForId (id: String): Element

derefter behøver opkaldskode ikke at håndtere et null-tilfælde, fordi det garanteres af kompilatoren og Kotlin-sproget, at det returnerede objekt ikke kan være nullt.

Ellers, hvis der er et ugyldigt objekt sendt til en metode, og sagen ikke håndteres, kompileres den ikke.

Lad os skrive en test case for Kotlin type-sikkerhed:

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

Vi ser her, at efter udførelse af metode findItemNameForId (), den returnerede type er af Kotlin Nullable. For at få adgang til et felt af objektet (id), skal vi håndtere sagen på kompileringstidspunktet. Metode lade() udføres kun, hvis et resultat ikke er ugyldigt. jegd felt kan tilgås inde i en lambda-funktion, fordi den er nul sikker.

En anden måde at få adgang til det ugyldige objektfelt er at bruge Kotlin-operatøren !!. Det svarer til:

hvis (resultat == null) {throwNpe (); } returnere resultat

Kotlin vil kontrollere, om objektet er et nul i så fald vil det kaste et NullPointerException, ellers vil det returnere et ordentligt objekt. Fungere throwNpe () er en intern Kotlin-funktion.

13. Dataklasser

En meget flot sprogkonstruktion, der kunne findes i Kotlin, er dataklasser (det svarer til "case class" fra Scala-sprog). Formålet med sådanne klasser er kun at opbevare data. I vores eksempel havde vi en Vare klasse, der kun indeholder dataene:

dataklasse Element (val id: String, val name: String)

Compileren opretter metoder til os hashCode (), lige med()og toString (). Det er god praksis at gøre dataklasser uforanderlige ved hjælp af en val nøgleord. Dataklasser kunne have standard feltværdier:

dataklasse Element (val id: String, val name: String = "unknown_name")

Vi ser det navn felt har en standardværdi "ukendt_navn".

14. Udvidelsesfunktioner

Antag, at vi har en klasse, der er en del af et tredjepartsbibliotek, men vi vil udvide den med en ekstra metode. Kotlin giver os mulighed for at gøre dette ved hjælp af udvidelsesfunktioner.

Lad os overveje et eksempel, hvor vi har en liste over elementer, og vi vil tage et tilfældigt element fra denne liste. Vi vil tilføje en ny funktion tilfældig() til 3. part Liste klasse.

Sådan ser det ud i Kotlin:

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

Det vigtigste at bemærke her er en signatur af metoden. Metoden er forud for et navn på den klasse, som vi tilføjer denne ekstra metode til.

Inde i udvidelsesmetoden fungerer vi på en række af en liste og bruger derfor det her gav brugsadgang til listeforekomstmetoder som er tom() eller tælle(). Så er vi i stand til at ringe tilfældig() metode på enhver liste, der er inden for dette omfang:

sjov getRandomElementOfList (liste: Liste): T? {return list.random ()}

Vi oprettede en metode, der tager en liste og derefter udfører brugerdefineret udvidelsesfunktion tilfældig() der var tidligere defineret. Lad os skrive en test case til vores nye funktion:

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

Muligheden for at definere funktioner, der "udvider" tredjepartsklasser, er en meget kraftig funktion og kan gøre vores kode mere kortfattet og læsbar.

15. Strengskabeloner

En meget flot funktion i Kotlin-sproget er en mulighed for at bruge skabeloner til Snors. Det er meget nyttigt, fordi vi ikke behøver at sammenkæde Snors manuelt:

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

Vi kan også evaluere et udtryk inde i ${} blok:

val itemManager = ItemManager ("cat_id", "db: // forbindelse") val result = "funktionsresultat: $ {itemManager.isFromSpecificCategory (" 1 ")}"

16. Kotlin / Java-interoperabilitet

Kotlin - Java-interoperabilitet er problemfrit let. Lad os antage, at vi har en Java-klasse med en metode, der fungerer Snor:

klasse StringUtils {public static String toUpperCase (String name) {return name.toUpperCase (); }}

Nu vil vi udføre denne kode fra vores Kotlin-klasse. Vi behøver kun at importere den klasse, og vi kunne udføre java-metoden fra Kotlin uden problemer:

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

Som vi ser, brugte vi java-metoden fra Kotlin-koden.

Opkald til Kotlin-kode fra en Java er også meget let. Lad os definere enkel Kotlin-funktion:

klasse MathematicsOperations {fun addTwoNumbers (a: Int, b: Int): Int {return a + b}}

Udfører addTwoNumbers () fra Java-kode er meget let:

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

Vi ser, at kald til Kotlin-koden var gennemsigtig for os.

Når vi definerer en metode i java, er returtypen en ugyldig, i Kotlin returneres værdi af en Enhed type.

Der er nogle specielle identifikatorer på Java-sprog ( er, objekt, i, ..) at når de bruges i Kotlin-kode, skal de undslippes. For eksempel kunne vi definere en metode, der har et navn objekt() men vi er nødt til at huske at undslippe dette navn, da dette er en særlig identifikator i java:

sjovt `objekt` (): Streng {return" dette er objekt "}

Så kunne vi udføre denne metode:

`objekt` ()

17. Konklusion

Denne artikel introducerer Kotlin-sproget, og det er de vigtigste funktioner. Det starter med at introducere enkle begreber som sløjfer, betingede udsagn og definere klasser. Viser derefter nogle mere avancerede funktioner som udvidelsesfunktioner og null sikkerhed.

Implementeringen af ​​alle disse eksempler og kodestykker findes i GitHub-projektet.


$config[zx-auto] not found$config[zx-overlay] not found