【问题标题】:Kotlin when(Pair<>), is there any other way?Kotlin when(Pair<>),还有其他方法吗?
【发布时间】:2018-07-12 22:48:31
【问题描述】:

我有一个 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()
}

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

for ((key, value) in hashMap) {
    println("$key $value)
}

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

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

虽然这对有效......如果我想做 3 件事情怎么办?

【问题讨论】:

    标签: kotlin


    【解决方案1】:

    for 循环示例中的语法是destructuring declaration,它基本上是在一行中声明对对象的多个成员变量的引用的语法糖。它不会反过来,因为 Kotlin 没有任意元组的机制。

    我真的想不出一个好看的方法来用两个以上的变量来做到这一点。我的想法是要么使用enum,它基本上就像这样的元组:

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

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

    fun Array<*>.whenCheat(vararg others: Any?): Boolean {
        return this contentEquals others
    }
    
    val array = arrayOf("GET", "foo")
    when {
       array.whenCheat("GET", "foo") -> getFoo()
       ...
    }
    

    我的怀疑是,通过对函数的响应图来更好地服务于这种事情。希望其他人提出更聪明的解决方案。

    【讨论】:

      【解决方案2】:

      另一种选择是使用data class。例如:

      data class Response(val verb: String, val type: String, val other: Int)
      
      // This is an example of what the functions could be... edit as needed
      val all = { _: Response -> "all"}
      val some = { _: Response -> "some"}
      val unknown = { _: Response -> "unknown"}
      
      val handlers = mapOf<Response, (Response) -> String>(
          Response("GET", "all", 200) to all,
          Response("GET", "some", 400) to some
          // and all your other mappings
      )
      

      然后,您可以像这样使用该地图:

      val myFun = handlers.getOrDefault(myResponse, unknown)
      

      【讨论】:

        【解决方案3】:

        如果您只是将数据捆绑在一个类中并覆盖其equals 方法,则可以将when 与任意数量的项目一起使用:

        class Person(
                var firstName: String = "",
                var lastName: String = "",
                var age: Int = 0,
                var rate: Int = 0) {
        
            override fun equals(other: Any?): Boolean {
                val otherPerson = other as Person
        
                return (
                        firstName.equals(otherPerson.firstName) &&
                        lastName.equals(otherPerson.lastName) &&
                        age.equals(otherPerson.age) &&
                        rate.equals(otherPerson.rate))
            }
        
            // just to avoid warning
            override fun hashCode(): Int {
                return super.hashCode()
            }
        }
        
        fun main(args: Array < String > ) {
            val p = Person("John", "Doe", 18, 2)
            when (p) {
                Person("Nick", "Doe", 18, 2) -> println("found at 1")
                Person("John", "Doe", 18, 2) -> println("found at 2")
                Person("Maria", "Doe", 18, 2) -> println("found at 3")
                else -> println("not found")
            }
        }
        

        【讨论】:

        • 这正是数据类擅长的地方:自动定义equalshashCode
        • 完全________
        【解决方案4】:

        如果我想做 3 个项目怎么办?

        使用Triple 代替Pair

        【讨论】:

          猜你喜欢
          • 2023-02-20
          • 1970-01-01
          • 2010-11-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-05-24
          • 1970-01-01
          相关资源
          最近更新 更多