区分Kotlin中模棱两可的扩展
当我提到rng.max
时,我遇到了编译器“不能在以下候选者中选择”的问题: rng:IntRange
:
inline val <T:Comparable<T>> ClosedRange<T>.max get() = endInclusive // max of range inline val <T:Comparable<T>> Iterable<T>.max get():T? = max() // max element
我认为这是因为一个ClosedRange
实现ClosedRange
和(间接通过IntProgression
) Iterable
。
如果我想编写一个适用于CharRange
, LongRange
和CharRange
(可能但不一定是扩展ClosedRange
)的扩展ClosedRange
,是否有任何可以明确解析为ClosedRange
语法,而不是相似名称的Iterable
在这种情况下扩展?
有没有我可以添加任何语法明确解决到ClosedRange,而不是在这种情况下,类似名为Iterable扩展?
在你的例子中,客户必须区分两个不明确的扩展。
只要告诉编译器你想使用哪种类型:
val intRange = 0..10 (intRange as ClosedRange<Int>).max
考虑下面的代码:
fun Any.someExtensionFunction() = "Any" fun String.someExtensionFunction() = "String" fun main(args: Array<String>) { val s = "xyz" // type String inferred println(s.someExtensionFunction()) println((s as Any).someExtensionFunction()) println((s as String).someExtensionFunction()) }
输出:
串
任何
串
正如你所看到的,编译器将总是调用继承结构中最低类型的扩展函数,除非明确地告知。
所以,s1m0nw1的答案是正确的。
如果要确保始终调用ClosedRange
getter,则可以将检查添加到Iterable
getter。 由于内联,额外的检查可能会被优化掉:
inline val <T:Comparable<T>> Iterable<T>.max get():T? = when(this) { is ClosedRange<*> -> endInclusive //Specific overload for ClosedRange else -> max() }