Reputation: 2317
I don't understand why the following two into
functions, would cause an 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
Why doesn't kotlin know given the type parameter which one to choose when I explicitly specify the type boo.into<Foo>{}.morph()
?
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)
And
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)
Can I resolve this somehow?
Upvotes: 0
Views: 1087
Reputation: 4982
The functions from the JVM point of view have the same type after type erasure, it will be something like (in Java):
public void into(Boo boo, Fucntion1 block);
A function return type is not taken into account for such resolution at the JVM level.
Use the @JvmName("unique name")
annotation with different parameters for each of the methods to ask Kotlin compiler to generate unique names for the methods at the JVM level.
UPD: You do not need the generic parameters for these functions, namely <Fiz>
and <Foo>
. You do not use them in the declarations, and Kotlin compiler cannot infer the types too
UPD2: The compiler will not be able to guess the type of the lambda that you call, so you may need to specify the type of it explicitly too, e.g.
val builder : FizMorphBuilder.() -> Unit = { /*the builder lambda */ }
val z = Boo().into(builder)
We use the declaration with an explicit type to explain what exact builder lambda signature we need at that point.
Upvotes: 2