Gids voor het blok "wanneer {}" in Kotlin

1. Inleiding

Deze tutorial introduceert de wanneer{} block in Kotlin-taal en laat de verschillende manieren zien waarop het kan worden gebruikt.

Om het materiaal in dit artikel te begrijpen, is basiskennis van de Kotlin-taal vereist. U kunt de inleiding van het Kotlin Language-artikel op Baeldung bekijken om meer over de taal te leren.

2. Kotlin's wanneer{} Blok

Wanneer{} block is in wezen een geavanceerde vorm van het schakelkast statement bekend van Java.

Als in Kotlin een overeenkomende case wordt gevonden, wordt alleen de code in het respectieve case-blok uitgevoerd en wordt de uitvoering voortgezet met de volgende instructie na de wanneer blok. Dit betekent in wezen dat er aan het einde van elk geen afbrekingsverklaringen nodig zijn geval blok.

Om het gebruik van wanneer{}, laten we een enum-klasse definiëren die de eerste letter in het machtigingsveld bevat voor enkele van de bestandstypen in Unix:

enum klasse UnixFileType {D, HYPHEN_MINUS, L} 
Laten we ook een hiërarchie van klassen definiëren die de respectieve Unix-bestandstypen modelleren:
verzegelde klasse UnixFile {abstract plezier getFileType (): UnixFileType klasse RegularFile (val content: String): UnixFile () {overschrijven plezier getFileType (): UnixFileType {return UnixFileType.HYPHEN_MINUS}} class Directory (val kinderen: lijst): UnixFile () {overschrijf plezier getFileType (): UnixFileType {retourneer UnixFileType.D}} klasse SymbolicLink (val originalFile: UnixFile): UnixFile () {overschrijf plezier getFileType (): UnixFileType {retourneer UnixFileType.L}}} 

2.1. Wanneer{} als een uitdrukking

Een groot verschil met de switchverklaring van Java is dat de wanneer{} block in Kotlin kan zowel als een statement als als een expressie worden gebruikt. Kotlin volgt de principes van andere functionele talen en flow-control-structuren zijn uitdrukkingen en het resultaat van hun evaluatie kan worden teruggestuurd naar de beller.

Als de geretourneerde waarde is toegewezen aan een variabele, zal de compiler controleren of het type geretourneerde waarde compatibel is met het type dat door de klant wordt verwacht en zal hij ons hiervan op de hoogte stellen als dit niet het geval is:

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

Er zijn twee dingen die u moet opmerken als u when als uitdrukking in Kotlin gebruikt.

Ten eerste is de waarde die wordt teruggestuurd naar de beller de waarde van het overeenkomende casusblok of met andere woorden de laatst gedefinieerde waarde in het blok.

Het tweede dat opvalt, is dat we moeten garanderen dat de beller een waarde krijgt. Om dit te laten gebeuren, moeten we ervoor zorgen dat de cases, in het when-blok, elke mogelijke waarde dekken die aan het argument kan worden toegewezen.

2.2. Wanneer{} als een uitdrukking met standaard case

Een standaard case komt overeen met elke argumentwaarde die niet overeenkomt met een normale case en wordt in Kotlin gedeclareerd met de anders clausule. In elk geval zal de Kotlin-compiler aannemen dat elke mogelijke argumentwaarde wordt gedekt door het when-blok en zal klagen als dat niet het geval is.

Om een ​​standaard case toe te voegen in Kotlin's wanneer uitdrukking:

@Test fun testWhenExpressionWithDefaultCase () {val fileType = UnixFileType.L val resultaat = wanneer (fileType) {UnixFileType.L -> "linken naar een ander bestand" else -> "geen link"} assertEquals ("linken naar een ander bestand", resultaat) } 

2.3. When {} Expressie met een case die een uitzondering oplevert

In Kotlin, werpen geeft een waarde van type terug Niets.

In dit geval, Niets wordt gebruikt om aan te geven dat de expressie een waarde niet heeft kunnen berekenen. Niets is het type dat erft van alle door de gebruiker gedefinieerde en ingebouwde typen in Kotlin.

Daarom, aangezien het type compatibel is met elk argument dat we zouden gebruiken in een wanneer block, is het volkomen geldig om een ​​uitzondering van een geval zelfs als de wanneer blok wordt gebruikt als een uitdrukking.

Laten we een when-uitdrukking definiëren waarbij een van de gevallen een uitzondering genereert:

@Test (verwacht = IllegalArgumentException :: class) fun testWhenExpressionWithThrowException () {val fileType = UnixFileType.L val resultaat: Boolean = wanneer (fileType) {UnixFileType.HYPHEN_MINUS -> true else -> throw IllegalArgumentException ("Verkeerd type bestand") }} 

2.4. Wanneer{} Gebruikt als een verklaring

We kunnen ook de wanneer blok als een statement.

In dit geval hoeven we niet elke mogelijke waarde voor het argument te dekken en de waarde die in elk gevalblok wordt berekend, wordt, indien aanwezig, gewoon genegeerd. Bij gebruik als een verklaring, de wanneer block kan op dezelfde manier worden gebruikt als hoe het schakelaar statement wordt gebruikt in Java.

Laten we de wanneer blok als een statement:

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

We kunnen aan het voorbeeld zien dat het niet verplicht is om alle mogelijke argumentwaarden te dekken wanneer we deze gebruiken wanneer als een statement.

2.5. Combineren Wanneer{} Gevallen

Kotlin's wanneer expression stelt ons in staat om verschillende gevallen tot één te combineren door de overeenkomende voorwaarden met een komma samen te voegen.

Er hoeft slechts één hoofdlettergebruik overeen te komen om het betreffende codeblok uit te voeren, dus de komma fungeert als een OF operator.

Laten we een case maken die twee voorwaarden combineert:

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

2.6. Wanneer{} Gebruikt zonder een argument

Met Kotlin kunnen we de argumentwaarde weglaten in de wanneer blok.

Dit verandert in wezen in een eenvoudig if-elseif expressie die opeenvolgend gevallen controleert en het codeblok van het eerste overeenkomende geval uitvoert. Als we het argument in het when-blok weglaten, moeten de case-expressies resulteren in true of false.

Laten we een wanneer blok dat het argument weglaat:

@Test fun testWhenWithoutArgument () {val fileType = UnixFileType.L val objectType = wanneer {fileType === UnixFileType.L -> "l" fileType === UnixFileType.HYPHEN_MINUS -> "-" fileType === UnixFileType.D - > "d" else -> "onbekend bestandstype"} assertEquals ("l", objectType)} 

2.7. Dynamische case-expressies

In Java is het schakelaar statement kan alleen worden gebruikt met primitieven en hun boxed types, enums en de Draad klasse. In tegenstelling tot, Met Kotlin kunnen we de wanneer blok met elk ingebouwd of door de gebruiker gedefinieerd type.

Bovendien is het niet vereist dat de gevallen constante uitdrukkingen zijn zoals in Java. Cases in Kotlin kunnen dynamische expressies zijn die tijdens runtime worden geëvalueerd. Gevallen kunnen bijvoorbeeld het resultaat zijn van een functie, zolang het functieretourtype maar compatibel is met het type wanneer blok argument.

Laten we een wanneer blok met dynamische case-expressies:

@Test fun testDynamicCaseExpression () {val unixFile = UnixFile.SymbolicLink (UnixFile.RegularFile ("Content")) wanneer {unixFile.getFileType () == UnixFileType.D -> println ("Het is een directory!") UnixFile.getFileType ( ) == UnixFileType.HYPHEN_MINUS -> println ("Het is een normaal bestand!") UnixFile.getFileType () == UnixFileType.L -> println ("Het is een zachte link!")}} 

2.8. Uitdrukkingen van bereik en collectie

Het is mogelijk om een ​​casus te definiëren in een wanneer blok dat controleert of een bepaalde verzameling of een reeks waarden het argument bevat.

Om deze reden biedt Kotlin de in operator, wat syntactische suiker is voor de bevat () methode. Dit betekent dat Kotlin achter de schermen het case-element vertaalt in naar collection.contains (element).

Om te controleren of het argument in een lijst staat:

@Test fun testCollectionCaseExpressions () {val regularFile = UnixFile.RegularFile ("Testinhoud") val symbolicLink = UnixFile.SymbolicLink (regularFile) val directory = UnixFile.Directory (listOf (regularFile, symbolicLink)) val isRegularFileInDirectory) = {when in directory.children -> true else -> false} val isSymbolicLinkInDirectory = wanneer {symbolicLink in directory.children -> true else -> false} assertTrue (isRegularFileInDirectory) assertTrue (isSymbolicLinkInDirectory)} 
Om te controleren of het argument binnen een bereik valt:
@Test fun testRangeCaseExpressions () {val fileType = UnixFileType.HYPHEN_MINUS val isCorrectType = wanneer (fileType) {in UnixFileType.D..UnixFileType.L -> true else -> false} assertTrue (isCorrectType)} 

Hoewel REGULAR_FILE type is niet expliciet opgenomen in het bereik, zijn rangtelwoord is tussen de rangtelwoorden van DIRECTORY en SYMBOLIC_LINK en daarom is de test geslaagd.

2.9. Is Case Operator en Smart Cast

We kunnen Kotlin's gebruiken is operator om te controleren of het argument een instantie van een bepaald type is. De is operator is vergelijkbaar met de instantie van operator in Java.

Kotlin biedt ons echter een functie genaamd "smart cast". Nadat we hebben gecontroleerd of het argument een instantie van een bepaald type is, hoeven we het argument niet expliciet naar dat type te casten, aangezien de compiler dat voor ons doet.

Daarom kunnen we de methoden en eigenschappen die in het opgegeven type zijn gedefinieerd, rechtstreeks in het casusblok gebruiken.

Om de is-operator te gebruiken met de "smart cast" -functie in een wanneer blok:

@Test fun testWhenWithIsOperatorWithSmartCase () {val unixFile: UnixFile = UnixFile.RegularFile ("Testinhoud") val resultaat = wanneer (unixFile) {is UnixFile.RegularFile -> unixFile.content is UnixFile.Directory -> unixFile.Directory -> unixFile {. it.getFileType ()} .joinToString (",") is UnixFile.SymbolicLink -> unixFile.originalFile.getFileType ()} assertEquals ("Testinhoud", resultaat)} 
Zonder expliciet te casten unixFile naar RegularFile, Directory of SymbolicLink, we konden gebruiken RegularFile.content, Directory.children, en SymbolicLink.originalFile respectievelijk.

2.10. wanneer Expressies en loops

Vanaf Kotlin 1.4 is het mogelijk om breken of doorgaan met een lus zelfs binnen een wanneer uitdrukking. Bijvoorbeeld:

val colours = setOf ("Red", "Green", "Blue") for (color in colours) {when (color) {"Red" -> break "Green" -> ga verder met "Blue" -> println ("This is blauw") } }

In het bovenstaande voorbeeld breken beëindigt de dichtstbijzijnde omsluitende lus en de doorgaan met gaat door naar de volgende stap, zoals verwacht. Vóór Kotlin 1.4 kwalificeerde zich echter alleen breken en doorgaan met waren toegestaan ​​in een wanneer uitdrukking in een lus:

[e-mail beschermd] voor (kleur in kleuren) {wanneer (kleur) {"Rood" -> [e-mail beschermd] "Groen" -> [e-mail beschermd] "Blauw" -> println ("Dit is blauw")}}

Zoals hierboven getoond, is de breken en doorgaan met zijn gekwalificeerd met de @LUS uitdrukking.

3. Conclusie

In dit artikel hebben we verschillende voorbeelden gezien van het gebruik van de wanneer blok aangeboden door de Kotlin-taal.

Ook al is het niet mogelijk om patroonafstemming te doen met wanneer in Kotlin, zoals het geval is met de overeenkomstige structuren in Scala en andere JVM-talen, de wanneer block is veelzijdig genoeg om ons deze functies totaal te laten vergeten.

De volledige implementatie van de voorbeelden voor dit artikel is te vinden op GitHub.