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

  • Android Development with Kotlin
  • Marcin Moskala Igor Wojda
  • 854字
  • 2021-07-02 18:48:38

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

主站蜘蛛池模板: 海林市| 镇江市| 宁国市| 泾源县| 星子县| 阳朔县| 邵阳县| 德令哈市| 和林格尔县| 遂宁市| 临夏县| 基隆市| 特克斯县| 丰台区| 宁夏| 河间市| 金寨县| 金寨县| 定南县| 东乡县| 朝阳县| 寻甸| 广宁县| 阿拉善左旗| 沙田区| 天等县| 旌德县| 丽江市| 瑞金市| 安西县| 双城市| 绥阳县| 磐安县| 县级市| 常州市| 正安县| 页游| 广丰县| 开平市| 三原县| 长春市|