Lambda kifejezések Kotlinban

1. Áttekintés

Ebben a cikkben a Lambdas-t fogjuk feltárni a Kotlin nyelven. Ne feledje, hogy a lambdák nem egyedülállóak Kotlin számára, és sok éve léteznek sok más nyelven.

A Lambdas kifejezések lényegében anonim függvények, amelyeket értékként kezelhetünk - átadhatjuk őket például argumentumként a metódusoknak, visszaadhatjuk őket, vagy bármi más dolgot megtehetünk, amit egy normális objektummal megtehetnénk.

2. Lambda meghatározása

Mint látni fogjuk, a Kotlin Lambdas nagyon hasonlít a Java Lambdas-ra. Itt többet megtudhat a Java Lambdas használatáról és néhány bevált módszerről.

A lambda meghatározásához ragaszkodnunk kell a szintaxishoz:

val lambdaName: Type = {argumentList -> codeBody}

A lambda egyetlen része, amely nem választható, a codeBody.

Az argumentumlista átugorható, ha legfeljebb egy argumentumot és típus gyakran következtethet a Kotlin fordító. Nem mindig van szükségünk változóra is, a lambda közvetlenül átadható metódus argumentumként.

A lambda-mondaton belüli utolsó parancs típusa a visszaadott típus.

2.1. Típus következtetés

Kotlin típusú következtetése lehetővé teszi a lambda típusának értékelését a fordítóban.

A lambda írása, amely a szám négyzetét adja, ugyanúgy íródik, mint:

val négyzet = {szám: Int -> szám * szám} val kilenc = négyzet (3)

Kotlin a fenti példát egy olyan függvénynek fogja értékelni, amelyre szükség van Int és visszatér egy Int:(Int) -> Int

Ha olyan lambdát akartunk létrehozni, amely az egyetlen argumentumszámát megszorozza 100-val, akkor ezt az értéket a-ként adja vissza Húr:

val magnitude100String = {input: Int -> val magnitude = input * 100 magnitude.toString ()} 

Kotlin meg fogja érteni, hogy ez a lambda típusú (Int) -> Karakterlánc.

2.2. Típusnyilatkozat

Esetenként Kotlin nem tud következtetni a típusainkra, és kifejezetten be kell jelentenünk a lambda típusát; akárcsak bármely más típusnál.

A minta az bemenet -> kimenetazonban ha a kód nem ad eredményt, akkor a típust használjuk Mértékegység:

val, hogy: Int -> Int = {három -> három}
val tovább: (String, Int) -> String = {str, int -> str + int}
val noReturn: Int -> Unit = {num -> println (num)}

Osztálybővítőként használhatjuk a lambdákat:

val other: String. (Int) -> String = {ez + it}

Az itt használt minta kissé eltér a többi általunk meghatározott lambdától. Zárójelben még vannak érveink, de a zárójelek előtt megvan az a típus, amelyhez ezt a lambdát fogjuk csatolni.

Ahhoz, hogy ezt a mintát a Húr hívjuk a Type.lambdaName (érvek)úgynevezett „másik” példánk:

fun extensionString (arg: String, num: Int): String {val másik: String. (Int) -> String = {this + it} visszatér arg.another (num)}

2.3. Visszatérve a Lambdából

A végső kifejezés az az érték, amelyet a lambda végrehajtása után adunk vissza:

val calcGrade = {évfolyam: Int -> mikor (évfolyam) {0-ban 40..40 -> "Nem sikerült" 41..70-ben -> "Jó" 71-ben..100 -> "Megkülönböztetés" más -> hamis}}

Az utolsó módszer az anonim függvénydefiníció kihasználása - kifejezetten meg kell határoznunk az argumentumokat és a return típust, és a return utasítást ugyanúgy használhatjuk, mint bármely más módszert:

val calcGrade = fun (évfolyam: Int): String {if (100. évfolyam) {return "Hiba"} else if (40. évfolyam) {return "Fail"} else "Megkülönböztetés"}

3. azt

A lambda egyetlen argumentumának rövidítése a „kulcsszó használataazt'. Ez az érték minden olyan magányt képvisel, amelyet átadunk a lambda függvénynek.

Ugyanezt fogjuk végrehajtani az egyes metódus a következő tömbön Ints:

val tömb = arrayOf (1, 2, 3, 4, 5, 6)

Először a lambda függvény hosszúkézi alakját vesszük szemügyre, majd ugyanezen kód rövidítéses alakja következik, aholazt’A következő tömb minden elemét képviseli.

Folyóírás:

array.forEach {item -> println (item * 4)}

Gyorsírás:

array.forEach {println (it * 4)}

4. A Lambdas megvalósítása

Nagyon röviden kitérünk arra, hogyan hívhatjuk a hatókörű lambdát, valamint hogy miként adhatjuk át a lambdát érvként.

Ha a lambda objektum hatókörébe tartozik, hívja meg, mint bármely más in-scope metódust, a nevét, zárójeleket és minden argumentumot használva:

fun invokeLambda (lambda: (Double) -> Boolean): Boolean {return lambda (4.329)}

Ha egy lambdát kell argumentumként átadni egy magasabb rendű módszerbe, öt lehetőségünk van.

4.1. Lambda objektum változó

Meglévő lambda objektum használatával, amint azt a 2. szakasz deklarálja, átadjuk az objektumot a metódusnak, mint bármely más argumentummal:

@Teszt móka, amikorPassingALambdaObject_thenCallTriggerLambda () {val lambda = {arg: Double -> arg == 4.329} val result = invokeLambda (lambda) assertTrue (result)}

4.2. Lambda Literal

A lambda változóhoz rendelése helyett a literált közvetlenül átadhatjuk a metódushívásnak:

Tesztelje a szórakozást, amikorPassingALambdaLiteral_thenCallTriggerLambda () {val result = invokeLambda ({true}) assertTrue (result)}

4.3. Lambda Literal a zárójeleken kívül

A lambda literálok másik mintája, amelyet a JetBrains ösztönöz - az, hogy a lambdát adjuk be utolsó argumentumként egy módszerhez, és a lambdát a metódushíváson kívülre helyezzük:

@Test fun whenPassingALambdaLiteralOutsideBrackets_thenCallTriggerLambda () {val result = invokeLambda {arg -> arg.isNaN ()} assertFalse (result)}

4.4. Módszer hivatkozások

Végül lehetőségünk van a módszerreferenciák használatára. Ezek hivatkozások a meglévő módszerekre.

Az alábbi példánkban azt vesszük Dupla :: isFinite. Ez a funkció ezután ugyanazt a szerkezetet veszi fel, mint a lambda, azonban ez a típus KFunction1 mivel egyetlen érve van, befogadja a Kettős és visszaadja a Logikai:

@Test fun whenPassingAFunctionReference_thenCallTriggerLambda () {val referencia = Dupla :: isFinite val eredmény = invokeLambda (referencia) assertTrue (eredmény)}

5. Kotlin Lambda Java-ban

Kotlin generált függvényinterfészeket használ a Java interakciójához. Itt találhatók a Kotlin-forráskódban.

Korlátoztuk az ezen generált osztályokkal átadható argumentumok számát. A jelenlegi határ 22; amelyet az interfész képvisel Funkció22.

Az a felépítése Funkció Az interfész általános jellemzői, hogy a lambda argumentumainak száma és száma, akkor ez az osztályok száma lesz a Types argumentum.

Az utolsó általános érv a visszatérés típusa:

import kotlin.jvm.functions. * nyilvános felület Function1: Funkció {public operator fun invoke (p1: P1): R}

Ha a Kotlin kódban nincs megadva visszatérési típus, akkor a lambda Kotlin-t ad vissza Mértékegység. A Java kódnak importálnia kell az osztályt a kotlin csomagolj és térj vissza nulla.

Az alábbiakban bemutatunk egy Kotlin Lambda hívást egy olyan projektből, amely része Kotlin és Java része:

import kotlin.Unit; import kotlin.jvm.functions.Function1; ... új Function1 () {@Orride public unit invoke (c ügyfél) {AnalyticsManager.trackFacebookLogin (c.getCreated ()); return null; }} 

Java8 használatakor Java lambda-t használunk a helyett Funkció névtelen osztály:

@Test void givenJava8_whenUsingLambda_thenReturnLambdaResult () {assertTrue (LambdaKt.takeLambda (c -> c> = 0)); }

6. Névtelen belső osztályok

Kotlinnak két érdekes módja van a névtelen belső osztályokkal való együttműködésre.

6.1. Object Expression

Amikor Kotlin Belső Névtelen Osztályt vagy Java Névtelen Osztályt hívunk, amely több módszerből áll, végre kell hajtanunk egy Objektum Kifejezést.

Ennek bemutatásához egy egyszerű interfészt és egy osztályt veszünk, amely elvégzi az adott felület megvalósítását, és a módszereket a függőnek hívja Logikai érv:

osztály Processzor {interfész ActionCallback {fun success (): String fun fail (): String} fun performEvent (döntés: Boolean, callback: ActionCallback): String {return if (döntés) {callback.success ()} else {callback.failure ()}}}

Anonim belső osztály létrehozásához az „objektum” szintaxist kell használnunk:

@Test fun givenMultipleMethods_whenCallingAnonymousFunction_thenTriggerSuccess () {val result = Processor (). PerformEvent (true, object: Processor.ActionCallback {override fun success () = "Siker" felülbírálja a szórakozás sikertelenségét () = "Hiba"}) assertEquals ("Siker" eredmény)}

6.2. Lambda kifejezés

Másrészt arra is lehetőségünk van, hogy inkább lambdát használjunk. A lambdas anonim belső osztály helyett történő használatának bizonyos feltételei vannak:

  1. Az osztály egy Java felület megvalósítása (nem Kotlin)
  2. az interfésznek max

Ha mindkét feltétel teljesül, használhatunk helyette lambda kifejezést.

Maga a lambda annyi argumentumot fog felvenni, mint amennyit a felület egyetlen metódusa tesz.

Gyakori példa a lambda használata a szokásos Java helyett Fogyasztó:

val list = ArrayList (2) list.stream () .forEach ({i -> println (i)})

7. Következtetés

Míg szintaktikailag hasonlóak, a Kotlin és a Java lambdas teljesen más tulajdonságok. A Java 6 megcélzásakor Kotlinnak átalakítania kell lambdáit a JVM 1.6-on belül hasznosítható struktúrává.

Ennek ellenére a Java 8 lambdas legjobb gyakorlatai továbbra is érvényesek.

További információ a lambda legjobb gyakorlatairól itt.

A kódrészletek, mint mindig, a GitHubon találhatók.


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