Vejledning til "når {}" blokeringen i Kotlin

1. Introduktion

Denne vejledning introducerer hvornår{} blokere på Kotlin-sprog og demonstrerer de forskellige måder, hvorpå det kan bruges.

For at forstå materialet i denne artikel er grundlæggende kendskab til Kotlin-sproget nødvendigt. Du kan se introduktionen til Kotlin Language-artiklen om Baeldung for at lære mere om sproget.

2. Kotlins hvornår{} Blok

Hvornår{} blok er i det væsentlige en avanceret form for afbryderkasse erklæring kendt fra Java.

I Kotlin, hvis der findes en matchende sag, udføres kun koden i den respektive sagsblok, og udførelsen fortsætter med den næste erklæring efter hvornår blok. Dette betyder i det væsentlige, at der ikke er behov for pauseudtalelser i slutningen af ​​hver sag blok.

For at demonstrere brugen af hvornår{}, lad os definere en enum-klasse, der indeholder det første bogstav i tilladelsesfeltet for nogle af filtyperne i Unix:

enum klasse UnixFileType {D, HYPHEN_MINUS, L} 
Lad os også definere et hierarki af klasser, der modellerer de respektive Unix-filtyper:
forseglet klasse UnixFile {abstrakt fun getFileType (): UnixFileType klasse RegularFile (val indhold: String): UnixFile () {tilsidesættelse fun getFileType (): UnixFileType {return UnixFileType.HYPHEN_MINUS}} klasse Directory (val børn: Liste): UnixFile () {override fun getFileType (): UnixFileType {return UnixFileType.D}} class SymbolicLink (val originalFile: UnixFile): UnixFile () {override fun getFileType (): UnixFileType {return UnixFileType.L}}} 

2.1. Hvornår{} som et udtryk

En stor forskel fra Java's switch-erklæring er, at det hvornår{} blok i Kotlin kan bruges både som en erklæring og som et udtryk. Kotlin følger principperne for andre funktionelle sprog, og flowkontrolstrukturer er udtryk, og resultatet af deres evaluering kan returneres til den, der ringer op.

Hvis den returnerede værdi er tildelt en variabel, vil compileren kontrollere, at typen af ​​returværdien er kompatibel med den type, som forventes af klienten, og vil informere os, hvis den ikke er:

@Test sjov testWhenExpression () {val directoryType = UnixFileType.D val objectType = når (directoryType) {UnixFileType.D -> "d" UnixFileType.HYPHEN_MINUS -> "-" UnixFileType.L -> "l"} assertEquals ("d ", objectType)} 

Der er to ting at bemærke, når du bruger når som et udtryk i Kotlin.

For det første er den værdi, der returneres til den, der ringer op, værdien af ​​den matchende sagblok eller med andre ord den sidst definerede værdi i blokken.

Den anden ting at bemærke er, at vi skal garantere, at den, der ringer op, får en værdi. For at dette kan ske, er vi nødt til at sikre, at sagerne i når-blokken dækker alle mulige værdier, der kan tildeles argumentet.

2.2. Hvornår{} som et udtryk med standardtilstand

En standardsag vil matche enhver argumentværdi, der ikke matches med en normal sag, og i Kotlin erklæres ved hjælp af andet klausul. Under alle omstændigheder antager Kotlin-kompilatoren, at enhver mulig argumentværdi er dækket af når-blokken og vil klage, hvis den ikke er det.

For at tilføje en standardsag i Kotlins hvornår udtryk:

@ Test sjov 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 {} udtryk med en sag, der kaster en undtagelse

I Kotlin, kaste returnerer en værdi af typen Ikke noget.

I dette tilfælde, Ikke noget bruges til at erklære, at udtrykket ikke kunne beregne en værdi. Ikke noget er den type, der arver fra alle brugerdefinerede og indbyggede typer i Kotlin.

Da typen derfor er kompatibel med ethvert argument, som vi bruger i en hvornår blok, er det helt gyldigt at kaste en undtagelse fra en sag selvom den hvornår blok bruges som udtryk.

Lad os definere et når-udtryk, hvor en af ​​tilfældene giver en undtagelse:

@Test (forventet = IllegalArgumentException :: klasse) sjov testWhenExpressionWithThrowException () {val fileType = UnixFileType.L val resultat: Boolsk = når (fileType) {UnixFileType.HYPHEN_MINUS -> sandt andet -> kast IllegalArgumentException ("Wrong type") }} 

2.4. Hvornår{} Brugt som en erklæring

Vi kan også bruge hvornår blokere som en erklæring.

I dette tilfælde behøver vi ikke dække alle mulige værdier for argumentet, og den værdi, der beregnes i hvert tilfælde, blokeres, hvis nogen, bare ignoreres. Når den bruges som en erklæring, hvornår kan bruges på samme måde som kontakt erklæring bruges i Java.

Lad os bruge hvornår bloker som en erklæring:

@Test sjov 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 at dække alle mulige argumentværdier, når vi bruger hvornår som en erklæring.

2.5. Kombinerer Hvornår{} Sager

Kotlins hvornår udtryk giver os mulighed for at kombinere forskellige tilfælde i et ved at sammenkæde de matchende betingelser med et komma.

Kun en sag skal matche for at den respektive blok kode skal udføres, så kommaet fungerer som et ELLER operatør.

Lad os oprette en sag, der kombinerer to betingelser:

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

2.6. Hvornår{} Brugt uden argument

Kotlin giver os mulighed for at udelade argumentværdien i hvornår blok.

Dette drejer sig i det væsentlige, når det er enkelt if-elseif udtryk, der sekventielt kontrollerer sager og udfører kodeblokken i den første matchende sag. Hvis vi udelader argumentet i når-blokken, skal sagsudtrykkene evalueres til enten sand eller falsk.

Lad os oprette en hvornår blok der udelader argumentet:

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

2.7. Dynamiske sagsudtryk

I Java er kontakt erklæring kan kun bruges med primitiver og deres boksede typer, enums og Snor klasse. I modsætning, Kotlin giver os mulighed for at bruge hvornår blokere med enhver indbygget eller brugerdefineret type.

Derudover er det ikke nødvendigt, at sagerne er konstante udtryk som i Java. Tilfælde i Kotlin kan være dynamiske udtryk, der evalueres ved kørsel. F.eks. Kan sager være resultatet af en funktion, så længe funktionens returretype er kompatibel med typen af hvornår blokere argument.

Lad os definere en hvornår blok med dynamiske sagsudtryk:

@Test sjov testDynamicCaseExpression () {val unixFile = UnixFile.SymbolicLink (UnixFile.RegularFile ("Content")) når {unixFile.getFileType () == UnixFileType.D -> println ("Det er en mappe!") UnixFile.getFileType ( ) == UnixFileType.HYPHEN_MINUS -> println ("Det er en almindelig fil!") UnixFile.getFileType () == UnixFileType.L -> println ("Det er et blødt link!")}} 

2.8. Range og Collection Case udtryk

Det er muligt at definere en sag i en hvornår blok der kontrollerer om en given samling eller en række værdier indeholder argumentet.

Af denne grund leverer Kotlin i operatør, som er syntaktisk sukker til indeholder() metode. Det betyder, at bag kulisserne oversætter Kotlin sagselementet i til collection.contains (element).

Sådan kontrolleres, om argumentet er på en liste:

@Test sjov testCollectionCaseExpressions () {val regularFile = UnixFile.RegularFile ("Test Content") val symbolicLink = UnixFile.SymbolicLink (regularFile) val directory = UnixFile.Directory (listOf (regularFile, symbolicLink)) val isRegularFileInDirectory = når (normalFile i directory.children -> true else -> false} val isSymbolicLinkInDirectory = når {symbolicLink i directory.children -> true else -> false} assertTrue (isRegularFileInDirectory) assertTrue (isSymbolicLinkInDirectory)} 
For at kontrollere, at argumentet er inden for et interval:
@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 type er ikke eksplicit indeholdt i området, dets ordinal er mellem ordinals af VEJVISER og SYMBOLIC_LINK og derfor er testen vellykket.

2.9. Er Sagsoperatør og Smart Cast

Vi kan bruge Kotlins er operatør for at kontrollere, om argumentet er en forekomst af en specificeret type. Det er operatøren ligner forekomst af operatør i Java.

Kotlin giver os dog en funktion kaldet “smart cast”. Når vi har kontrolleret, om argumentet er en forekomst af en given type, behøver vi ikke eksplicit at kaste argumentet til den type, da kompilatoren gør det for os.

Derfor kan vi bruge de metoder og egenskaber, der er defineret i den givne type direkte i sagsblokken.

At bruge is-operatøren med funktionen “smart cast” i en hvornår blok:

@ Test sjov 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 ("Testindhold", resultat)} 
Uden eksplicit casting unixFile til RegularFile, Vejviser eller SymbolicLink, kunne vi bruge RegularFile.content, Directory.børnog SymbolicLink.originalFile henholdsvis.

2.10. hvornår Udtryk og sløjfer

Fra og med Kotlin 1.4 er det muligt at pause eller Blive ved en sløjfe selv inde i en hvornår udtryk. For eksempel:

val farver = setOf ("Rød", "Grøn", "Blå") for (farve i farver) {når (farve) {"Rød" -> bryde "Grøn" -> fortsæt "Blå" -> println ("Dette er blå ")}}

I ovenstående eksempel pause afslutter den nærmeste lukkende sløjfe og Blive ved fortsætter til næste trin som forventet. Før Kotlin 1.4 kvalificerede sig imidlertid kun pause og Blive ved blev tilladt i en hvornår udtryk inde i en løkke:

[e-mail-beskyttet] for (farve i farver) {når (farve) {"Rød" -> [e-mail-beskyttet] "Grøn" -> [e-mail-beskyttet] "Blå" -> println ("Dette er blå")}}

Som vist ovenfor er pause og Blive ved er kvalificeret med @LOOP udtryk.

3. Konklusion

I denne artikel har vi set flere eksempler på, hvordan du bruger hvornår blok tilbudt af Kotlin-sproget.

Selvom det ikke er muligt at foretage mønstermatchning ved hjælp af hvornår i Kotlin, som det er tilfældet med de tilsvarende strukturer på Scala og andre JVM - sprog, hvornår block er alsidig nok til at få os til at glemme alt om disse funktioner.

Den komplette implementering af eksemplerne til denne artikel kan findes på GitHub.