Metódy rozšírenia v Kotline

1. Úvod

Kotlin predstavuje koncept metód rozšírenia - ktoré sú praktický spôsob rozšírenia existujúcich tried o novú funkcionalitu bez použitia dedičnosti alebo akýchkoľvek foriem vzoru Decorator - po definovaní rozšírenia. môžeme ho v podstate použiť - keďže bol súčasťou pôvodného rozhrania API.

To môže byť veľmi užitočné pri uľahčení čítania a údržby nášho kódu, pretože sme schopní pridať metódy, ktoré sú špecifické pre naše potreby a umožňujú, aby sa javili ako súčasť pôvodného kódu, aj keď nemáme prístup k zdroje.

Napríklad budeme možno musieť vykonať únik XML v a String. V štandardnom kóde Java by sme museli napísať metódu, ktorá to dokáže, a nazvať ju:

Reťazec uniknutý = escapeStringForXml (vstup);

Zatiaľ čo úryvok je napísaný v Kotline, dá sa nahradiť:

val escaped = input.escapeForXml ()

Nielenže je to ľahšie čitateľné, ale IDE budú môcť ponúknuť metódu ako možnosť automatického dopĺňania rovnako, ako keby išlo o štandardnú metódu na String trieda.

2. Štandardné metódy rozšírenia knižnice

Štandardná knižnica Kotlin je dodávaná s niektorými metódami rozšírenia, ktoré sú pripravené na použitie.

2.1. Metódy rozšírenia upravujúce kontext

Existujú niektoré všeobecné rozšírenia, ktoré je možné v našej aplikácii použiť na všetky typy. Tieto by sa mohli použiť na zabezpečenie toho, aby bol kód spustený vo vhodnom kontexte, a v niektorých prípadoch na zabezpečenie toho, že premenná nebude mať hodnotu null.

Ukazuje sa, že s najväčšou pravdepodobnosťou využívame rozšírenia bez toho, aby sme si to uvedomovali.

Jedným z najobľúbenejších je pravdepodobne nech () metóda, ktorú je možné volať na akýkoľvek typ v Kotline - odovzdajme jej funkciu, ktorá sa vykoná na počiatočnej hodnote:

val name = "Baeldung" val uppercase = name .let {n -> n.toUpperCase ()}

Je to podobné ako s mapa () metóda z Voliteľné alebo Prúd triedy - v tomto prípade odovzdáme funkciu predstavujúcu akciu, ktorá prevedie danú String do jeho horného znaku.

Premenná názov je známy ako príjemca hovoru pretože je to premenná, na ktorú metóda rozšírenia koná.

Toto funguje skvele s operátorom bezpečného volania:

meno valca = možnoGetName () val veľké písmeno = meno? .let {n -> n.toUpperCase ()}

V tomto prípade blok prešiel na nech () sa hodnotí, iba ak je premenná názov bol nenulový. To znamená, že vo vnútri bloku je hodnota n je zaručene nenulové. Viac o tomto tu.

Existujú aj iné alternatívy nech () to môže byť tiež užitočné, v závislosti od našich potrieb.

The run () rozšírenie funguje rovnako ako nech (), ale prijímač je poskytovaný ako toto hodnota vo vnútri volaného bloku:

val name = "Baeldung" val uppercase = name.run {toUpperCase ()}

použiť () funguje rovnako ako run (), ale namiesto vrátenia hodnoty z poskytnutého bloku vráti prijímač.

Využime to použiť () na reťazové volania:

val languages ​​= mutableListOf () languages.apply {add ("Java") add ("Kotlin") add ("Groovy") add ("Python")} .apply {remove ("Python")} 

Všimnite si, ako je náš kód stručnejší a expresívnejší, keď ho nemusíte výslovne používať toto alebo to.

Tiež () rozšírenie funguje rovnako ako nech (), ale vráti prijímač rovnakým spôsobom použiť () robí:

val languages ​​= mutableListOf () languages.also {list -> list.add ("Java") list.add ("Kotlin") list.add ("Groovy")} 

The takeIf () rozšírenie je vybavené predikátom pôsobiacim na prijímač, a ak sa tento predikát vráti pravda potom vráti prijímač alebo nulový inak - funguje to podobne ako kombinácia bežnej mapy() a filter () metódy:

val language = getLanguageUsed () val coolLanguage = language.takeIf {l -> l == "Kotlin"} 

TakeUnless () rozšírenie je rovnaké ako takeIf () ale s obrátenou predikátovou logikou.

val language = getLanguageUsed () val oldLanguage = language.takeUnless {l -> l == "Kotlin"} 

2.2. Metódy rozšírenia pre zbierky

Kotlin pridáva k štandardným kolekciám Java veľké množstvo metód rozšírenia, vďaka ktorým je možné s našim kódom ľahšie pracovať.

Tieto metódy sa nachádzajú vo vnútri _Collections.kt, _Ranges.kta _Sequences.kt, ako aj _Arrays.kt pre rovnocenné metódy, ktoré sa majú uplatňovať na Polia namiesto toho. (Pamätajte, že v Kotline Polia sa dá zaobchádzať rovnako ako s Zbierky)

Týchto metód rozšírenia je tu príliš veľa na diskusiu, takže si tieto súbory prezrite, aby ste zistili, čo je k dispozícii.

Okrem zbierok pridáva Kotlin do knižnice značné množstvo metód rozšírenia String trieda - definované v _Strings.kt. Tieto nám umožňujú liečiť Struny akoby to boli zbierky postáv.

Všetky tieto metódy rozšírenia spolupracujú, čo nám umožňuje písať výrazne čistejšie a ľahšie udržiavateľné kódy bez ohľadu na to, s akým typom kolekcie pracujeme.

3. Písanie našich metód rozšírenia

Čo ak teda potrebujeme rozšíriť triedu o novú funkcionalitu - buď zo štandardnej knižnice Java alebo Kotlin Standard alebo zo závislej knižnice, ktorú používame?

Metódy rozšírenia sa píšu ako každá iná metóda, ale trieda prijímača sa poskytuje ako súčasť názvu funkcie oddelená bodkou.

Napríklad:

fun String.escapeForXml (): String {....}

Toto definuje novú funkciu s názvom escapeForXml ako rozšírenie k String triedy, čo nám umožňuje nazvať to tak, ako je to popísané vyššie.

Vo vnútri tejto funkcie môžeme získať prístup k prijímaču pomocou toto, rovnako ako by sme to napísali do String trieda samotná:

fun String.escapeForXml (): String {return this .replace ("&", "&") .replace ("<", "", ">")}

3.1. Písanie všeobecných metód rozšírenia

Čo ak chceme napísať metódu rozšírenia, ktorá sa má všeobecne použiť na viac typov? Mohli by sme len predĺžiť akýkoľvek typ, ktorý je ekvivalentom Objekt triedy v Jave - ale existuje lepší spôsob.

Metódy rozšírenia je možné použiť na všeobecný aj konkrétny prijímač:

fun T.concatAsString (b: T): String {return this.toString () + b.toString ()}

To by sa dalo použiť na akýkoľvek typ, ktorý spĺňa všeobecné požiadavky, a vo vnútri funkcie toto hodnota je bezpečná.

Napríklad pomocou vyššie uvedeného príkladu:

5.concatAsString (10) // kompiluje "5" .concatAsString ("10") // kompiluje 5.concatAsString ("10") // nekompiluje

3.2. Písanie metód rozšírenia Infix

Metódy Infix sú užitočné pri písaní kódu v štýle DSL, pretože umožňujú volanie metód bez bodiek a zátvoriek:

infix fun Number.toPowerOf (exponent: Number): Double {return Math.pow (this.toDouble (), exponent.toDouble ())}

Teraz to môžeme nazvať rovnako ako ktorákoľvek iná metóda infix:

3 toPowerOf 2 // 9 9 toPowerOf 0,5 // 3

3.3. Metódy rozšírenia operátora zápisu

Ako príponu by sme mohli napísať aj operátorovú metódu.

Metódy operátora sú také, ktoré nám umožňujú využívať namiesto skratky operátora skratku operátora namiesto celého názvu metódy - napr plus operátorská metóda sa dá nazvať pomocou + operátor:

zábava pre operátora List.times (podľa: Int): List {return this.map {it * by}}

Toto opäť funguje rovnako ako akákoľvek iná metóda operátora:

listOf (1, 2, 3) * 4 // [4, 8, 12]

4. Volanie funkcie rozšírenia Kotlin z Javy

Pozrime sa teraz, ako funguje Java s rozšíreniami Kotlin.

Všeobecne je každá metóda rozšírenia, ktorú definujeme v Kotline, k dispozícii na použitie v Jave. Mali by sme si však uvedomiť, že infix metóda musí byť stále volaná s bodkou a zátvorkami. To isté platí pre rozšírenia operátora - nemôžeme použiť iba znak plus (+). Tieto zariadenia sú k dispozícii iba v Kotlin.

Nemôžeme však volať niektoré štandardné metódy knižnice Kotlin v jazyku Java nechajme alebo uplatniť, pretože sú označené symbolom @InlineOnly.

4.1. Viditeľnosť funkcie Custom Extension v jazyku Java

Využime jednu z predtým definovaných funkcií rozšírenia - String.escapeXml (). Náš súbor obsahujúci metódu prípony sa volá StringUtil.kt.

Teraz, keď potrebujeme zavolať metódu rozšírenia z Javy, musíme použiť názov triedy StringUtilKt. Upozorňujeme, že musíme pridať Kt prípona:

Reťazec xml = "ahoj"; Reťazec escapedXml = StringUtilKt.escapeForXml (xml); assertEquals ("ahoj", uniknutéXml);

Venujte pozornosť prvému escapeForXml parameter. Tento ďalší argument je typu prijímača s rozšírenou funkciou. Kotlin s funkciou rozšírenia na najvyššej úrovni je čistý Java triedy statickou metódou. Preto treba nejako odovzdať originál String.

A samozrejme, rovnako ako v Java, môžeme použiť statický import:

import statického kom.baeldung.kotlin.StringUtilKt. *;

4.2. Volanie vstavanej metódy rozšírenia Kotlin

Kotlin pomáha nám ľahšie a rýchlejšie písať kód poskytovaním mnohých zabudovaných funkcií rozšírení. Napríklad je tu String.veľké písmená () metóda, ktorú je možné volať priamo z Java:

Názov reťazca = "john"; Reťazec capitalizedName = StringsKt.capitalize (meno); assertEquals ("John", capitalizedName);

Avšak nemôžeme volať metódy rozšírenia označené @InlineOnly od Java, napríklad:

vložená zábava T.let (blok: (T) -> R): R

4.3. Premenovanie vygenerovanej statickej triedy Java

Už vieme, že a Kotlin rozširujúca funkcia je statická Java metóda. Premenujeme vygenerovaný Java triedy s anotáciou @file: JvmName (meno: reťazec).

Toto je potrebné pridať do hornej časti súboru:

@file: JvmName ("Strings") balíček com.baeldung.kotlin fun String.escapeForXml (): String {return this .replace ("&", "&") .replace ("<", "", ">" )}

Teraz, keď chceme zavolať metódu rozšírenia, musíme jednoducho pridať znak Struny názov triedy:

Strings.escapeForXml (xml);

Stále môžeme pridať statický import:

import statického kom.baeldung.kotlin.Stringy. *;

5. Zhrnutie

Metódy rozšírenia sú užitočné nástroje na rozšírenie typov, ktoré už v systéme existujú - buď preto, že nemajú funkcie, ktoré potrebujeme, alebo jednoducho na uľahčenie správy konkrétnej oblasti kódu.

Videli sme tu niekoľko metód rozšírenia, ktoré sú pripravené na použitie v systéme. Ďalej sme preskúmali rôzne možnosti metód rozšírenia. Niektoré príklady týchto funkcií nájdete na GitHub.


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