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

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).

主站蜘蛛池模板: 肥西县| 海淀区| 五台县| 延寿县| 鄂托克前旗| 图木舒克市| 松原市| 德州市| 江北区| 青海省| 富宁县| 介休市| 巴楚县| 泸水县| 叶城县| 湖北省| 科尔| 通州区| 西华县| 佛教| 改则县| 新乡县| 鸡西市| 道真| 六盘水市| 南安市| 赤壁市| 黑龙江省| 岳阳县| 黔南| 蒲江县| 托克托县| 垣曲县| 朝阳县| 奈曼旗| 黄龙县| 弥勒县| 孟津县| 新绛县| 垦利县| 永川市|