Kotlin when(Pair<>),还有其他办法吗?

Tra*_*ggs 10 kotlin

我有一个when想要匹配两件事的构造:

when (activeRequest.verb to activeRequest.resourceType) {
    GET to "all" -> allGet()
    PUT to "foo" -> fooPut()
    GET to "foo" -> fooGet()
    POST to "bar" -> barPost()
    GET to "bar" -> barGet()
    COPY to "bar" -> barCopy()
    DELETE to "bar" -> barDelete()
    else -> logMismatch()
}
Run Code Online (Sandbox Code Playgroud)

使用to对构造函数是执行此操作的唯一方法吗?Pair 的使用似乎很奇怪(尽管它有效)。我很难找到它,因为代码片段像

for ((key, value) in hashMap) {
    println("$key $value)
}
Run Code Online (Sandbox Code Playgroud)

让我觉得我应该能够在when代码中做类似的事情,例如

when (activeRequest.verb, activeRequest.resourceType) {
    (GET, "all") -> allGet()
    (PUT, "foo") -> fooPut()
   ...
    else -> logMismatch()
}
Run Code Online (Sandbox Code Playgroud)

当这对工作时...如果我想做 3 件事情怎么办?

eme*_*sso 4

for 循环示例中的语法是解构声明,它基本上是在一行中声明对对象的多个成员变量的引用的语法糖。它不会以相反的方式返回,因为 Kotlin 没有用于任意元组的机制。

我实在想不出一种漂亮的方法来使用两个以上的变量来做到这一点。我想到的选择是使用基本上作为元工作的枚举,如下所示:

enum class Response(val verb: String, val type: String) {

    GET_FOO("GET", "foo"),
    ...
    INVALID("?", "?");

    companion object {
        fun from(verb: String, type: String): Response {
            for(response in values()) {
                if(response.verb == verb && response.type == type)
                    return response
            }

            return INVALID
        }
    }
}

when(Response.from(activeRequest.verb, activeRequest.resourceType)) {
    GET_FOO -> getFoo()
    ...
}
Run Code Online (Sandbox Code Playgroud)

或者使用数组。不幸的是,Kotlin 数组相等性不是按内容计算的,因此最终会得到大量样板文件,并且when语法看起来不再很好。(我添加了一个扩展功能来使它更好一点,但我仍然不喜欢它):

fun Array<*>.whenCheat(vararg others: Any?): Boolean {
    return this contentEquals others
}

val array = arrayOf("GET", "foo")
when {
   array.whenCheat("GET", "foo") -> getFoo()
   ...
}
Run Code Online (Sandbox Code Playgroud)

我怀疑这种事情最好通过函数响应图来实现。希望其他人能提出更聪明的解决方案。