【问题标题】:Is it possible to return the same type as the type parameter in when statement是否可以在when语句中返回与类型参数相同的类型
【发布时间】:2017-06-16 11:52:50
【问题描述】:

例如:

fun <T> f(a: T): T =
    when (a) {
        a is Int -> 0  // if T is Int, then return Int
        a is String -> ""  // if T is String, then return String
        else -> throw RuntimeException()  // Otherwise, throw an exception so that the return type does not matter.
    }

它给出了编译错误:

Error:(3, 20) The integer literal does not conform to the expected type T
Error:(4, 23) Type mismatch: inferred type is String but T was expected

【问题讨论】:

    标签: generics types kotlin


    【解决方案1】:

    之后您可以将结果转换为T。你不会得到任何编译器帮助,你会收到警告,但至少它确实编译:

    fun <T> f(a: T): T =
        when {
            a is Int -> 0  // if T is Int, then return Int
            a is String -> ""  // if T is String, then return String
            else -> throw RuntimeException()  // Otherwise, throw an exception so that the return type does not matter.
        } as T
    

    注意这里when (a)是不必要的,when {就足够了。

    【讨论】:

    • 你也可以写when(a),在每种情况下都写is Int -&gt;。您不会以这种方式对每种情况重复a
    【解决方案2】:

    目前,当 Kotlin 编译器分析函数时,它不会为主体部分假定类型参数的某些特殊情况。

    相反,使用类型参数T 的代码应该对任何T 都是正确的。返回一个Int,其中预期T 被认为是不安全的,因为它的分析不够深入以证明如果函数到达该分支,T 始终是Int 的超类型。

    一种选择是对T 进行未经检查的强制转换,如@nhaarman 的回答,从而表示您确定类型是正确的。

    另一种解决方案是对您的函数进行多个重载,以使用不同的类型:

    fun f(a: Int) = 1
    fun f(a: String) = ""
    fun f(a: Any): Nothing = throw RuntimeException()
    

    在这种情况下,编译器会根据你传递的参数来选择函数重载,这与将单个泛型函数专门用于某个类型的参数相反,这对编译器来说是一个更简单的任务,因为它不涉及函数体内的任何类型分析。


    还有类似的问题:

    【讨论】:

      猜你喜欢
      • 2018-12-24
      • 2019-12-23
      • 1970-01-01
      • 2011-12-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多