class MapBuilder<T,U> {
operator fun invoke(arg: T): MapBuilder<T, U> {
return this
}
operator fun invoke(arg: U): MapBuilder<T, U> {
return this
}
}
of course it's don't work due to JVM limitations.
Platform declaration clash: The following declarations have the same JVM signature (invoke(Ljava/lang/Object;)Lcom/test/tests/MapBuilder;):
operator fun invoke(arg: T): MapBuilder<T, U> defined in com.test.tests.MapBuilder
operator fun invoke(arg: U): MapBuilder<T, U> defined in com.test.tests.MapBuilder
Any idea, how I can implement this?
These methods could effectively have the same signature given unknown generic types. Therefore the base case as presented is ambiguous to the JVM. So you just need to give them an alternative name from which the JVM (and Java or other JVM language) would view them. You use the @JvmName
annotation on one or both of them to give them internal names. This won't affect Kotlin and the name you use from your Kotlin code at all which will see them as they were prior.
class MapBuilder<T,U> {
@JvmName("invokeWithT")
operator fun invoke(arg: T): MapBuilder<T, U> {
return this
}
@JvmName("InvokeWithU") // technically don't need both of these
operator fun invoke(arg: U): MapBuilder<T, U> {
return this
}
}
Now you are fine and can use them independently.
val builder = MapBuilder<String, Integer>()
builder("hi") // success!
builder(123) // success!
Be warned that if T
and U
are ambiguous you could get additional errors when trying to call them.
val builder = MapBuilder<String, String>()
builder("hi") // error!
Error:(y, x) Kotlin: Overload resolution ambiguity:
@JvmName public final operator fun invoke(arg: String): MapBuilder defined in MapBuilder
@JvmName public final operator fun invoke(arg: String): MapBuilder defined in MapBuilder
You can also work around this problem if you can define your generics in a way that they possibly won't overlap and be the same class. You might get the error depending on the actual generic parameters chosen, but at least your base declaration would be allowed. This is described in more detail in Zoe's answer.