过载分辨率含糊不清...

时间:2018-07-04 12:46:55

标签: kotlin method-overriding method-reference default-parameters

这里有些沉闷的超载:

class Dummy() {
    fun f(x: Unit) : String = "Disco"
    fun f(x: Unit, y: Unit = Unit) : String = "Mambo"
}

我不确定为什么会这样,但这可行:

fun main(args: Array<String>) {
    println(Dummy().f(Unit))           // Echoes “Disco”
}

但是,那不是:

fun main(args: Array<String>) {
    println((Dummy::f)(Dummy(), Unit)) // Fails: “Overload resolution ambiguity”
}

对结果差异有何见解?

3 个答案:

答案 0 :(得分:1)

当您致电Dummy::f时,有两个同名的候选人 f

fun f(x: Unit) : String = "Disco"
fun f(x: Unit, y: Unit = Unit) : String = "Mambo"

然后,编译器不知道采用哪个。这是因为函数参考没有指定参数,即使将其中一个的签名更改为:

fun f(x: Int) : String = "Disco"
fun f(s: String) : String = "Mambo"

您将有一个问题,因为不可能使用以下语句来推断类型:Dummy::f

请注意,函数引用主要用于避免创建lambda。


例如,如果您具有:(不同名称)

class Dummy() {
    fun f(x: Unit) : String = "Disco"
    fun g(x: Int) : String = "Mambo"
}

fun main(args: Array<String>) {
    val f = Dummy::f
    val g = Dummy::g
}

f的类型为KFunction2<Dummy, Unit, String> 并且g类型为KFunction2<Dummy, Int, String>

但是,如果您定义:(同名)

class Dummy() {
    fun f(x: Unit) : String = "Disco"
    fun f(x: Int) : String = "Mambo"
}

fun main(args: Array<String>) {
    val f = Dummy::f
    val g = Dummy::f
}

由于将限制编译器的性能,并且由于存在两个具有相同名称的函数,因此无法推断该函数的类型,因此将出现“重载分辨率歧义”错误。要澄清的问题不是参数的数量,而是使用具有许多候选对象的函数引用。

答案 1 :(得分:1)

如果更改函数名称很简单,则只需对其进行更改,

如果您使用的是库或什至是String之类的原始类,则可以创建如下扩展名:

fun String.myToLowerCase(): String = this.toLowerCase()
fun Dummy.myF(): String = "Disco"

答案 2 :(得分:0)

如果您不能更改其中一个函数的名称来解决歧义引用(例如,因为它们在库中),则还可以创建一个简单的函数代理。

这甚至可以做成扩展功能:

// unchangeable overloaded functions
class Dummy() {
    fun f(x: Unit) : String = "Disco"
    fun f(x: Unit, y: Unit = Unit) : String = "Mambo"
}
//your code

fun Dummy.g(x:Unit, y:Unit = Unit) = f(x, y)

val functionF = Dummy::f //fine
val functionF2 = Dummy::g //fine