区分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和(间接通过IntProgressionIterable

如果我想编写一个适用于CharRangeLongRangeCharRange (可能但不一定是扩展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() }