使用主题时,Kotlin 的“when”表达式是否支持复合布尔表达式?

geg*_*geg 8 kotlin

是否可以在when(subject) { ... }块中提供复合布尔表达式?

以下不会编译

val num: Any = 2
when(num) {
    /* compound boolean expression that uses implicit subject expression
     * and an independent expression */
    is Number && true -> println("TRUE")
    else -> println("FALSE")
}
Run Code Online (Sandbox Code Playgroud)

以下将编译,但结果是FALSE. 这是预期的行为吗?

val num: Any = 2
when(num) {
    num is Number && true -> println("TRUE")
    else -> println("FALSE")
}
Run Code Online (Sandbox Code Playgroud)

我有很长的时间条件列表,其中大多数只使用隐式主题,但有几个需要辅助条件

acd*_*ior 9

使用表达式时是否可以提供多个布尔条件when(subject) { ... }

是的,您可以使用(逗号)分隔多个when 条件,

例如,以下whens 具有完全相同的行为。可运行的游乐场演示在这里

fun withoutComma(arg: Any?): String {
  return when(arg) {
    is String -> "FOO!"  // returned when arg is an instance of String
    true -> "bar!"       // returned when arg == true
    is Long -> "FOO!"    // returned when arg is an instance of Long
    false -> "bar!"      // returned when arg == false
    null -> "FOO!"       // returned when arg == null
    is Int -> "bar!"     // returned when arg is an instance of Int
    else -> "else!"
  }
}

fun withComma(arg: Any?): String {
  return when(arg) {
    is String, is Long, null -> "FOO!"  // returned when arg is an instance of String, or when arg is an instance of Long, or when arg == null
    true, false, is Int -> "bar!"       // returned when arg == true, or when arg == false, or when arg is an instance of Int
    else -> "else!"
  }
}

fun main() {
    listOf("s", true, 999L, false, null, 123, emptyList<Any>()).forEach {
        println("$it -> withoutComma: ${withoutComma(it)}")
        println("$it -> withComma: ${withComma(it)}")
    }
}

// Prints:
// s -> withoutComma: FOO!
// s -> withComma: FOO!
// true -> withoutComma: bar!
// true -> withComma: bar!
// 999 -> withoutComma: FOO!
// 999 -> withComma: FOO!
// false -> withoutComma: bar!
// false -> withComma: bar!
// null -> withoutComma: FOO!
// null -> withComma: FOO!
// 123 -> withoutComma: bar!
// 123 -> withComma: bar!
// [] -> withoutComma: else!
// [] -> withComma: else!
Run Code Online (Sandbox Code Playgroud)


Dim*_*kos 7

//First case
//Prints TRUE if the num value is numeric and true.Anything else prints FALSE
 val num: Any = 2
    when {
        num is Number && true -> println("TRUE")
        else -> println("FALSE")
    }
//Second case
//Prints true if the value is numeric OR true.Anything else prints FALSE
val num: Any = 2
when(num){
         is Number , true -> println("TRUE")
        else -> println("FALSE")
    }
    
Run Code Online (Sandbox Code Playgroud)

  • 嗨,迈赫拉德。谢谢你指导我。对此,我真的非常感激。我编辑了我的答案。我也发表了评论,但由于某种原因我没有看到它。 (2认同)

Rol*_*and 6

关于第一个问题:看看它的when语法。仅允许直接使用inand (以及它们的负对应项)。is否则你只有表情。

现在关于你的第二个,首先将其转换为if/else语句可能会有所帮助。基本上你的when将会如下所示:

if (num == ((num is Number) && true)) println("TRUE")
else println("FALSE")
Run Code Online (Sandbox Code Playgroud)

如果看一下这个,就会清楚为什么它总是打印FALSE。虽然num is Number变得truetrue && true仍然true,但它num == true是错误的,因为num甚至不是布尔值;-)

或者换句话说:将您的“主题”when与每个条件进行比较(感谢Bwvolleyball的评论)。


然而我不太明白(但这也可能是我对语法的误解)......看看语法,似乎以下是可能的:

when {
  is Number -> TODO()
}
Run Code Online (Sandbox Code Playgroud)

但正如人们所预料的那样:事实并非如此……但最后一句话只是一个旁注。

  • 除此之外,Kotlin 正在将 `when()` 子句中的项目与正在打开的项目进行比较。此示例将始终打印“two”: `val num = 2 when(num) { num2.equals(num2) -&gt; println("true") num2 -&gt; println("two") else -&gt; println("false" ) }` 因为就像OP提到的那样,`num == true`(我们从`num2.equals(num2)`得到true)是假的,所以它被跳过。抱歉,格式不正确,没有好的方法可以在评论中做到这一点...... (2认同)