Veiledning til "når {}" blokkeringen i Kotlin

1. Introduksjon

Denne opplæringen introduserer når{} blokk på Kotlin-språk og demonstrerer de forskjellige måtene den kan brukes på.

For å forstå materialet i denne artikkelen, er grunnleggende kunnskap om Kotlin-språket nødvendig. Du kan ta en titt på introduksjonen til Kotlin Language-artikkelen om Baeldung for å lære mer om språket.

2. Kotlin's når{} Blokkere

Når{} block er egentlig en avansert form for bryterveske uttalelse kjent fra Java.

I Kotlin, hvis en matchende sak blir funnet, blir bare koden i den respektive saksblokken utført, og kjøringen fortsetter med neste uttalelse etter når blokkere. Dette betyr i hovedsak at det ikke er behov for brudduttalelser på slutten av hver sak blokkere.

For å demonstrere bruken av når{}la oss definere en enumklasse som inneholder den første bokstaven i tillatelsesfeltet for noen av filtypene i Unix:

enum klasse UnixFileType {D, HYPHEN_MINUS, L} 
La oss også definere et hierarki av klasser som modellerer de respektive Unix-filtypene:
forseglet klasse UnixFile {abstrakt moro getFileType (): UnixFileType klasse RegularFile (val content: String): UnixFile () {override fun getFileType (): UnixFileType {return UnixFileType.HYPHEN_MINUS}} class Directory (val children: List): UnixFile () {override fun getFileType (): UnixFileType {return UnixFileType.D}} class SymbolicLink (val originalFile: UnixFile): UnixFile () {override fun getFileType (): UnixFileType {return UnixFileType.L}}} 

2.1. Når{} som et uttrykk

En stor forskjell fra Java's bryteruttalelse er at de når{} blokk i Kotlin kan brukes både som en uttalelse og som et uttrykk. Kotlin følger prinsippene til andre funksjonelle språk og flytkontrollstrukturer er uttrykk, og resultatet av evalueringen kan returneres til den som ringer.

Hvis verdien returnert er tildelt en variabel, vil kompilatoren sjekke at typen returverdi er kompatibel med typen som forventes av klienten, og vil informere oss i tilfelle den ikke er:

@Test fun testWhenExpression () {val directoryType = UnixFileType.D val objectType = when (directoryType) {UnixFileType.D -> "d" UnixFileType.HYPHEN_MINUS -> "-" UnixFileType.L -> "l"} assertEquals ("d ", objectType)} 

Det er to ting du må legge merke til når du bruker når som et uttrykk i Kotlin.

Først er verdien som returneres til den som ringer, verdien av den matchende saksblokken eller med andre ord den sist definerte verdien i blokken.

Den andre tingen å legge merke til er at vi må garantere at den som ringer får en verdi. For at dette skal skje, må vi sørge for at sakene i når-blokken dekker alle mulige verdier som kan tildeles argumentet.

2.2. Når{} som et uttrykk med standard sak

Et standardtilfelle vil samsvare med en hvilken som helst argumentverdi som ikke matches med en normal sak, og i Kotlin blir deklarert ved hjelp av ellers klausul. I alle fall vil Kotlin-kompilatoren anta at alle mulige argumentverdier dekkes av når-blokken, og vil klage i tilfelle det ikke er det.

For å legge til en standard sak i Kotlin når uttrykk:

@Test fun testWhenExpressionWithDefaultCase () {val fileType = UnixFileType.L val result = when (fileType) {UnixFileType.L -> "linking to another file" else -> "not a link"} assertEquals ("linking to another file", resultat) } 

2.3. Når {} Uttrykk med et tilfelle som gir unntak

I Kotlin, kaste returnerer en verdi av typen Ingenting.

I dette tilfellet, Ingenting brukes til å erklære at uttrykket ikke klarte å beregne en verdi. Ingenting er typen som arver fra alle brukerdefinerte og innebygde typer i Kotlin.

Derfor, siden typen er kompatibel med ethvert argument som vi vil bruke i en når blokk, er det helt gyldig å kaste et unntak fra en sak selv om når blokk brukes som uttrykk.

La oss definere et når-uttrykk der en av tilfellene gir unntak:

@Test (forventet = IllegalArgumentException :: klasse) morsom testWhenExpressionWithThrowException () {val fileType = UnixFileType.L val resultat: Boolsk = når (fileType) {UnixFileType.HYPHEN_MINUS -> ekte annet -> kast IllegalArgumentException fil (") Feil }} 

2.4. Når{} Brukes som en uttalelse

Vi kan også bruke når blokker som en uttalelse.

I dette tilfellet trenger vi ikke å dekke alle mulige verdier for argumentet, og verdien beregnet i hvert tilfelle blokkeres, hvis noen, bare ignoreres. Når den brukes som en uttalelse, når kan brukes på samme måte som bytte om uttalelse brukes i Java.

La oss bruke når blokker som en uttalelse:

@Test fun testWhenStatement () {val fileType = UnixFileType.HYPHEN_MINUS når (fileType) {UnixFileType.HYPHEN_MINUS -> println ("Regular file type") UnixFileType.D -> println ("Directory file type")}} 

Vi kan se fra eksemplet at det ikke er obligatorisk å dekke alle mulige argumentverdier når vi bruker når som en uttalelse.

2.5. Kombinere Når{} Saker

Kotlin er når uttrykk tillater oss å kombinere forskjellige tilfeller i ett ved å sammenkoble samsvaringsbetingelsene med et komma.

Bare ett tilfelle må matche for at den respektive kodeblokken skal kjøres, så kommaet fungerer som et ELLER operatør.

La oss lage en sak som kombinerer to forhold:

@Test fun testCaseCombination () {val fileType = UnixFileType.D val frequentFileType: Boolean = when (fileType) {UnixFileType.HYPHEN_MINUS, UnixFileType.D -> true else -> false} assertTrue (frequentFileType)} 

2.6. Når{} Brukt uten argument

Kotlin lar oss utelate argumentverdien i når blokkere.

Dette blir i hovedsak når det er enkelt if-elseif uttrykk som sekvensielt sjekker saker og utfører kodeblokken til den første matchende saken. Hvis vi utelater argumentet i når-blokken, bør saksuttrykkene evalueres til enten sant eller usant.

La oss lage en når blokk som utelater argumentet:

@Test morsom testWhenWithoutArgument () {val fileType = UnixFileType.L val objectType = når {fileType === UnixFileType.L -> "l" fileType === UnixFileType.HYPHEN_MINUS -> "-" fileType === UnixFileType.D - > "d" annet -> "ukjent filtype"} assertEquals ("l", objectType)} 

2.7. Dynamiske tilfelleuttrykk

I Java er bytte om uttalelse kan bare brukes med primitiver og deres innrammede typer, enums og String klasse. I motsetning, Kotlin tillater oss å bruke når blokker med hvilken som helst innebygd eller brukerdefinert type.

I tillegg er det ikke påkrevd at sakene er konstante uttrykk som i Java. Tilfeller i Kotlin kan være dynamiske uttrykk som evalueres i løpetid. For eksempel kan tilfeller være et resultat av en funksjon så lenge funksjonstypen er kompatibel med typen når blokker argument.

La oss definere en når blokk med dynamiske saksuttrykk:

@Test fun testDynamicCaseExpression () {val unixFile = UnixFile.SymbolicLink (UnixFile.RegularFile ("Content")) når {unixFile.getFileType () == UnixFileType.D -> println ("Det er en katalog!") UnixFile.getFileType ( ) == UnixFileType.HYPHEN_MINUS -> println ("Det er en vanlig fil!") UnixFile.getFileType () == UnixFileType.L -> println ("Det er en myk lenke!")}} 

2.8. Range og Collection Case uttrykk

Det er mulig å definere en sak i en når blokk som sjekker om en gitt samling eller et verdiområde inneholder argumentet.

Av denne grunn gir Kotlin i operatør, som er syntaktisk sukker for inneholder () metode. Dette betyr at bak kulissene oversetter Kotlin sakselementet i til collection.contains (element).

Slik sjekker du om argumentet er i en liste:

@Test fun testCollectionCaseExpressions () {val regularFile = UnixFile.RegularFile ("Test Content") val symbolicLink = UnixFile.SymbolicLink (regularFile) val directory = UnixFile.Directory (listOf (regularFile, symbolicLink)) val isRegularFileInDirectory = når (vanlig i directory.children -> true else -> false} val isSymbolicLinkInDirectory = når {symbolicLink i directory.children -> true else -> false} assertTrue (isRegularFileInDirectory) assertTrue (isSymbolicLinkInDirectory)} 
Slik sjekker du at argumentet er innenfor et område:
@Test fun testRangeCaseExpressions () {val fileType = UnixFileType.HYPHEN_MINUS val isCorrectType = when (fileType) {in UnixFileType.D..UnixFileType.L -> true else -> false} assertTrue (isCorrectType)} 

Selv om REGULAR_FILE typen er ikke eksplisitt inneholdt i området, dens ordinal er mellom ordinalene til DIREKTIV og SYMBOLIC_LINK og derfor er testen vellykket.

2.9. Er Saksoperatør og Smart Cast

Vi kan bruke Kotlins er operatøren for å sjekke om argumentet er en forekomst av en spesifisert type. De er operatøren ligner på tilfelle av operatør i Java.

Imidlertid gir Kotlin oss en funksjon kalt “smart cast”. Etter at vi har sjekket om argumentet er en forekomst av en gitt type, trenger vi ikke å kaste argumentet eksplisitt til den typen siden kompilatoren gjør det for oss.

Derfor kan vi bruke metodene og egenskapene som er definert i den gitte typen direkte i saksblokken.

Å bruke is-operatøren med "smart cast" -funksjonen i a når blokkere:

@Test fun testWhenWithIsOperatorWithSmartCase () {val unixFile: UnixFile = UnixFile.RegularFile ("Test Content") val result = when (unixFile) {is UnixFile.RegularFile -> unixFile.content is UnixFile.Directory -> unixFile.child. it.getFileType ()} .joinToString (",") er UnixFile.SymbolicLink -> unixFile.originalFile.getFileType ()} assertEquals ("Test Content", result)} 
Uten å eksplisitt støpe unixFile til RegularFile, Katalog eller SymbolicLink, kunne vi bruke RegularFile.content, Katalog.barn, og SymbolicLink.originalFile henholdsvis.

2.10. når Uttrykk og løkker

Fra og med Kotlin 1.4 er det mulig å gå i stykker eller Fortsette en løkke selv inne i en når uttrykk. For eksempel:

val farger = setOf ("Rød", "Grønn", "Blå") for (farge i farger) {når (farge) {"Rød" -> bryte "Grønn" -> fortsett "Blå" -> println ("Dette er blå ")}}

I eksemplet ovenfor, gå i stykker avslutter nærmeste innesluttende sløyfe og Fortsette fortsetter til neste trinn, som forventet. Før Kotlin 1.4 kvalifiserte det seg imidlertid bare gå i stykker og Fortsette ble tillatt i en når uttrykk inne i en løkke:

[e-postbeskyttet] for (farge i farger) {når (farge) {"Rød" -> [e-postbeskyttet] "Grønn" -> [e-postbeskyttet] "Blå" -> println ("Dette er blått")}}

Som vist ovenfor, gå i stykker og Fortsette er kvalifisert med @LØKKE uttrykk.

3. Konklusjon

I denne artikkelen har vi sett flere eksempler på hvordan du bruker når blokk tilbudt av Kotlin-språket.

Selv om det ikke er mulig å gjøre mønstermatching ved hjelp av når i Kotlin, som det er tilfellet med tilsvarende strukturer i Scala og andre JVM-språk, når block er allsidig nok til at vi helt glemmer disse funksjonene.

Den komplette implementeringen av eksemplene for denne artikkelen finner du på GitHub.


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