官术网_书友最值得收藏!

The when expression

The when expression in Kotlin is a multiway branch statement. The when expression is designed as a more powerful replacement for the Java switch... case statement. The when statement often provides a better alternative than a large series of if... else if statements, as it provides more concise syntax. Let's look at an example:

    when (x) { 
        1 -> print("x == 1") 
        2 -> print("x == 2") 
        else -> println("x is neither 1 nor 2") 
    } 

The when expression matches its argument against all branches one after another until the condition of some branch is satisfied. This behavior is similar to Java's switch... case, but we do not have to write a redundant break statement after every branch.

Similar to the if clause, we can use when either as a statement ignoring the returned value or as an expression and assign its value to a variable. If when is used as an expression, the value of the last line of the satisfied branch becomes the value of the overall expression. If it is used as a statement, the value is simply ignored. As usual, the else branch is evaluated if none of the previous branches satisfy the condition:

    val vehicle = "Bike" 
 
    val message= when (vehicle) { 
        "Car" -> { 
            // Some code 
            "Four wheels" 
        } 
        "Bike" -> { 
            // Some code 
            "Two wheels" 
        } 
        else -> { 
            //some code 
            "Unknown number of wheels" 
        } 
    } 
 
    println(message) //Prints: Two wheels 

Each time a branch has more than one instruction, we must place it inside the code block, defined by two braces {... }. If when is treated as an expression (the result of evaluating when is assigned to a variable), the last line of each block is treated as the return value. We have seen the same behavior with an if expression, so by now you have probably figured out that this is common behavior across many Kotlin constructs, including lambdas, which will be discussed further later in the book.

If when is used as an expression, the else branch is mandatory, unless the compiler can prove that all possible cases are covered with branch conditions. We can also handle many matching arguments in a single branch using commas to separate them:

    val vehicle = "Car" 
 
    when (vehicle) { 
        "Car", "Bike" -> print("Vehicle")
        else -> print("Unidentified funny object") 
    } 

Another nice feature of when is the ability to check variable type. We can easily validate that a value is or !is of a particular type. Smart casts become handy again, because we can access the methods and properties of a matching type in a branch block without any extra checks:

    val name = when (person) { 
        is String -> person.toUpperCase()
        is User -> person.name 
//Code is smart casted to String, so we can
//call String class methods
//...
}

In a similar way, we can check which range or collection contains a particular value. This time, we'll use the is and !is keywords:

    val riskAssessment = 47 
 
    val risk = when (riskAssessment) { 
        in 1..20 -> "negligible risk" 
        !in 21..40 -> "minor risk" 
        !in 41..60 -> "major risk" 
        else -> "undefined risk" 
    } 
 
    println(risk) // Prints: major risk 

Actually, we can put any kind of expression on the right-hand side of the when branch. It can be a method call or any other expression. Consider the following example where the second when expression is used for the else statement:

    val riskAssessment = 80 
    val handleStrategy = "Warn" 
 
    val risk = when (riskAssessment) { 
        in 1..20 -> print("negligible risk") 
        !in 21..40 -> print("minor risk") 
        !in 41..60 -> print("major risk") 
        else -> when (handleStrategy){ 
            "Warn" -> "Risk assessment warning"  
            "Ignore" -> "Risk ignored" 
            else -> "Unknown risk!" 
        }  
    } 
 
    println(risk) // Prints: Risk assessment warning 

As we can see, when is a very powerful construct, allowing more control than Java's switch, but it is even more powerful because it is not limited only to checking values for equality. In a way, it can even be used as a replacement for an if... else if chain. If no argument is supplied to the when expression, the branch conditions behave as Boolean expressions, and a branch is executed when its condition is true:

private fun getPasswordErrorId(password: String) = when { 
    password.isEmpty() -> R.string.error_field_required 
    passwordInvalid(password) -> R.string.error_invalid_password 
    else -> null 
} 

All the presented examples require an else branch. Each time when all the possible cases are covered, we can omit an else branch (exhaustive when). Let's look at the simplest example with Boolean:

    val large:Boolean = true 
         
    when(large){ 
        true -> println("Big") 
        false -> println("Big") 
    } 

The compiler can verify that all possible values are handled, so there is no need to specify an else branch. The same logic applies to enums and sealed classes, which will be discussed in Chapter 4, Classes and Objects.

Checks are performed by the Kotlin compiler, so we have certainty that any case will not be missed. This reduces the possibility of a common Java bug where the developer forgets to handle all the cases inside the switch statement (although polymorphism is usually a better solution).

主站蜘蛛池模板: 长丰县| 攀枝花市| 墨脱县| 章丘市| 尉氏县| 钟山县| 赫章县| 巧家县| 肇庆市| 景洪市| 新乡市| 闽清县| 兖州市| 淮安市| 奈曼旗| 林周县| 四会市| 涡阳县| 灵石县| 甘谷县| 明光市| 察隅县| 白沙| 锦州市| 勐海县| 邻水| 舒城县| 湘阴县| 石泉县| 天镇县| 弋阳县| 桂阳县| 布拖县| 民勤县| 贺兰县| 澎湖县| 平遥县| 克东县| 高淳县| 博客| 讷河市|