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

时间:2021-04-03 16:55:25

Consider this class with two functions, one with Int argument, the other with a generic one:

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

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

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

When it is parameterized as C<Int, SomeType>, K is Int, and both functions match the calls, resulting into an error:

当它被参数化为C , K是Int,并且两个函数都匹配调用,导致了一个错误: 时,sometype>

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

Overload resolution ambiguity. All these functions match:

重载决议歧义。所有这些功能匹配:

  • public final fun f(index: Int): SomeType defined in C
  • 公共final fun f(索引:Int):在C中定义的SomeType。
  • public final fun f(key: Int): Pair<Int, SomeType>? defined in C
  • public final fun f(key: Int): Pair ?在C中定义 ,>

How do I call whichever f I want in this case?

在这种情况下,我怎么称呼我想要的f ?

2 个解决方案

#1


7  

If you are lucky enough to have different parameter names of the functions, using named arguments will do the trick:

如果您足够幸运,有不同的函数参数名,那么使用命名参数就可以了:

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

Otherwise, if the parameter names are the same (or defined in Java), one possible workaround is to perform unchecked casts to make the compiler choose the desired option:

否则,如果参数名称是相同的(或在Java中定义),那么一个可能的解决方案是执行未选中的转换,使编译器选择所需的选项:

  • To call f(index: Int), you can use

    要调用f(索引:Int),您可以使用。

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

    The cast to C<*, SomeType> makes K equivalent to in Nothing, out Any, meaning that there's no valid argument for f(key: K), so the call is naturally resolved to f(index: Int), but you need to cast the result back, because otherwise it is Pair<Any, SomeType>.

    cast到C<*, SomeType>使K等于in Nothing, out Any,意思是对f(key: K)没有有效的参数,所以这个调用自然地解析为f(index: Int),但是您需要将结果返回,否则它是Pair ,>

  • To call f(key: K), use:

    调用f(key: K),使用:

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

    Similarly, the cast to C<Any, SomeType> changes the signature of the desired function to f(key: Any), and to call it, just upcast 1 to Any.

    类似地,cast到C 将所需函数的签名更改为f(key: Any),并将其命名为upcast 1。 ,>

It's all the same in case of several type parameters *ing (e.g. f(key: K) and f(value: V) when K and V are both SomeType), just use named arguments or cast the object to ban one of the functions (in Nothing) or to make it accept Any.

当K和V都是某种类型的时候,它们都是相同的,比如f(key: K)和f(value: V),只使用命名的参数或者抛出对象来禁止函数中的一个(在任何情况下),或者让它接受任何函数。

#2


0  

Kotlin stdlib uses convention fun fAt(index: Int) to resolve such cases.

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

#1


7  

If you are lucky enough to have different parameter names of the functions, using named arguments will do the trick:

如果您足够幸运,有不同的函数参数名,那么使用命名参数就可以了:

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

Otherwise, if the parameter names are the same (or defined in Java), one possible workaround is to perform unchecked casts to make the compiler choose the desired option:

否则,如果参数名称是相同的(或在Java中定义),那么一个可能的解决方案是执行未选中的转换,使编译器选择所需的选项:

  • To call f(index: Int), you can use

    要调用f(索引:Int),您可以使用。

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

    The cast to C<*, SomeType> makes K equivalent to in Nothing, out Any, meaning that there's no valid argument for f(key: K), so the call is naturally resolved to f(index: Int), but you need to cast the result back, because otherwise it is Pair<Any, SomeType>.

    cast到C<*, SomeType>使K等于in Nothing, out Any,意思是对f(key: K)没有有效的参数,所以这个调用自然地解析为f(index: Int),但是您需要将结果返回,否则它是Pair ,>

  • To call f(key: K), use:

    调用f(key: K),使用:

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

    Similarly, the cast to C<Any, SomeType> changes the signature of the desired function to f(key: Any), and to call it, just upcast 1 to Any.

    类似地,cast到C 将所需函数的签名更改为f(key: Any),并将其命名为upcast 1。 ,>

It's all the same in case of several type parameters *ing (e.g. f(key: K) and f(value: V) when K and V are both SomeType), just use named arguments or cast the object to ban one of the functions (in Nothing) or to make it accept Any.

当K和V都是某种类型的时候,它们都是相同的,比如f(key: K)和f(value: V),只使用命名的参数或者抛出对象来禁止函数中的一个(在任何情况下),或者让它接受任何函数。

#2


0  

Kotlin stdlib uses convention fun fAt(index: Int) to resolve such cases.

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