如何处理泛型函数的重载解析模糊性?

考虑这个类有两个函数,一个是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>() mf(1) 

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

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

在这种情况下,我如何打电话给我想要的?

如果你足够幸运有不同的参数名称的函数,使用命名参数将做的伎俩:

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

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

  • 要调用f(index: Int) ,可以使用

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

    转换到C<*, SomeType> 使K等价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) ),在使用命名参数或者SomeType 禁止其中一个函数的情况下, in Nothing )或使其接受Any

Kotlin stdlib使用约定fun fAt(index: Int)来解决这种情况。