如何使用泛型来处理函数的重载决策模糊性?

时间:2016-11-21 14:51:47

标签: generics kotlin ambiguous overload-resolution

考虑这个有两个函数的类,一个带有Int参数,另一个带有泛型函数:

class C<K, V> {
    // ...

    operator fun f(index: Int): Pair<K, V> = ...
    operator fun f(key: K): V = ...
}

当参数化为C<Int, SomeType>时,KInt,并且两个函数都与调用匹配,从而导致错误:

val m = C<Int, SomeType>()
m.f(1)
  

重载分辨率模糊。所有这些功能都匹配:

     
      {li> public final fun f(index: Int): SomeTypeC 中定义   {li> public final fun f(key: Int): Pair<Int, SomeType>?C 中定义   

在这种情况下如何拨打我想要的f个?

2 个答案:

答案 0 :(得分:9)

如果你有幸拥有这些功能的不同参数名称,那么使用named arguments就可以了:

m.f(index = 1) // calls f(index: Int)
m.f(key = 1)   // calls f(key: K)

否则,如果参数名称相同(或在Java中定义),一种可能的解决方法是执行unchecked casts以使编译器选择所需的选项:

  • 要致电f(index: Int),您可以使用

    @Suppress("UNCHECKED_CAST")
    val s = (m as C<*, SomeType>).f(1) as Pair<Int, SomeType>
    

    转化为C<*, SomeType> makes K equivalent to in Nothing, out Any,意味着f(key: K)没有有效参数,因此调用自然会解析为f(index: Int),但您需要转换结果返回,因为否则它是Pair<Any, SomeType>

  • 要致电f(key: K),请使用:

    @Suppress("UNCHECKED_CAST")
    val s = (m as C<Any, SomeType>).f(1 as Any)
    

    同样,转化为C<Any, SomeType>会将所需功能的签名更改为f(key: Any),并将其调用,只需将1转换为Any

如果几个类型参数发生冲突(例如f(key: K)f(value: V) KV都是SomeType),情况都是一样的,只需使用命名参数或将对象强制转换为禁止其中一个函数(in Nothing)或使其接受Any

答案 1 :(得分:0)

Kotlin stdlib使用约定fun fAt(index: Int)来解决此类问题。