解决过载分辨率的歧义

时间:2019-03-05 23:31:48

标签: kotlin

我不明白为什么以下两个into函数会导致Overload resolution ambiguity:

public fun <Fiz> Boo.into(block: FizMorphBuilder.() -> Unit): FizMorphBuilder defined in com.ltrojanowski.morph
public fun <Foo> Boo.into(block: FooMorphBuilder.() -> Unit): FooMorphBuilder defined in com.ltrojanowski.morph

当我明确指定类型boo.into<Foo>{}.morph()时,为什么Kotlin不知道给定的type参数是哪个?

class FooMorphBuilder(
    var a: String?,
    var b: Double?,
    var c: Int?,
    var d: Float?,
    var e: List<String>?
) : MorphBuilder<Foo> {
    override fun morph(): Foo = Foo(a = a!!, b = b!!, c = c!!, d = d!!, e = e!!)
}

fun <Foo> Boo.into(block: FooMorphBuilder.() -> Unit): FooMorphBuilder = FooMorphBuilder(this.a,
        this.b, this.c, this.d, this.e).apply(block)

class FizMorphBuilder(
    var a: String?,
    var b: Double?,
    var c: Int?,
    var d: Float?,
    var e: List<String>?
) : MorphBuilder<Fiz> {
    override fun morph(): Fiz = Fiz(a = a!!, b = b!!, c = c!!, d = d!!, e = e!!)
}

fun <Fiz> Boo.into(block: FizMorphBuilder.() -> Unit): FizMorphBuilder = FizMorphBuilder(this.a,
        this.b, this.c, this.d, this.e).apply(block)

我能以某种方式解决这个问题吗?

1 个答案:

答案 0 :(得分:2)

从JVM角度来看,函数在类型擦除后具有相同的类型,这类似于(在Java中):

public void into(Boo boo, Fucntion1 block);

在JVM级别上,此类解析不考虑函数返回类型。

为每个方法使用带有不同参数的@JvmName("unique name")批注,以要求Kotlin编译器为JVM级别的方法生成唯一的名称。

UPD :这些功能不需要通用参数,即<Fiz><Foo>。您不要在声明中使用它们,而且Kotlin编译器也无法推断类型

UPD2 : 编译器将无法猜测您调用的lambda的类型,因此您可能还需要明确指定其类型,例如

val builder : FizMorphBuilder.() -> Unit = { /*the builder lambda */ }
val z = Boo().into(builder)

我们使用带有显式类型的声明来说明此时需要的确切生成器lambda签名。