如何处理泛型函数的重载解析歧义?
How to deal with an overload resolution ambiguity of functions with generics?
考虑这个 class 有两个函数,一个有 Int
参数,另一个有一个通用函数:
class C<K, V> {
// ...
operator fun f(index: Int): Pair<K, V> = ...
operator fun f(key: K): V = ...
}
参数化为C<Int, SomeType>
时,K
为Int
,两个函数都匹配调用,导致报错:
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
public final fun f(key: Int): Pair<Int, SomeType>?
defined in C
在这种情况下,如何调用我想要的 f
?
如果你有幸拥有不同的函数参数名称,使用 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)
当 K
和 V
都是 SomeType
时,只需使用命名参数或将对象转换为 ban 函数之一 (in Nothing
) 或使其接受 Any
.
Kotlin stdlib 使用约定 fun fAt(index: Int)
来解决此类情况。
考虑这个 class 有两个函数,一个有 Int
参数,另一个有一个通用函数:
class C<K, V> {
// ...
operator fun f(index: Int): Pair<K, V> = ...
operator fun f(key: K): V = ...
}
参数化为C<Int, SomeType>
时,K
为Int
,两个函数都匹配调用,导致报错:
val m = C<Int, SomeType>()
m.f(1)
Overload resolution ambiguity. All these functions match:
public final fun f(index: Int): SomeType
defined inC
public final fun f(key: Int): Pair<Int, SomeType>?
defined inC
在这种情况下,如何调用我想要的 f
?
如果你有幸拥有不同的函数参数名称,使用 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>
makesK
equivalent toin 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)
当 K
和 V
都是 SomeType
时,只需使用命名参数或将对象转换为 ban 函数之一 (in Nothing
) 或使其接受 Any
.
Kotlin stdlib 使用约定 fun fAt(index: Int)
来解决此类情况。