Rob Elliot
09/12/2024, 2:07 PMAccidental override: The following declarations have the same JVM signature (size()I): fun size(): Int
Code in thread.Rob Elliot
09/12/2024, 2:10 PMpublic interface TreeNode {
int size();
}
Kotlin interface:
interface Map<K, out V> {
val size: Int
}
My code:
class Foo(
private val theSize: Int,
) : TreeNode, Map<String, Any?> {
override val size: Int = theSize
override fun size(): Int = theSize
}
Rob Elliot
09/12/2024, 2:13 PMephemient
09/12/2024, 2:15 PMephemient
09/12/2024, 2:16 PMRob Elliot
09/12/2024, 2:16 PMrogercaplan
09/12/2024, 2:42 PMVampire
09/12/2024, 2:47 PMVampire
09/12/2024, 3:02 PM@JvmName
to fix the problem?
If I for example add @get:JvmName("size")
to override val size: Int = theSize
, I get also a declaration clash. Not accidental as it was done explicitly, but I'd guess you can use it to avoid the accidental clash.Rob Elliot
09/12/2024, 3:32 PMkotlin.collections.Map
and a Java interface... if I create my own Kotlin interface it works ok.
package example;
public interface JavaInterface {
int size();
}
package example
class Implementation : Map<String, Any>, JavaInterface {
override val entries: Set<Map.Entry<String, Any>> get() = TODO("Not yet implemented")
override val keys: Set<String> get() = TODO("Not yet implemented")
override val size: Int get() = TODO("Not yet implemented")
override val values: Collection<Any> get() = TODO("Not yet implemented")
override fun isEmpty(): Boolean = TODO("Not yet implemented")
override fun get(key: String): Any? = TODO("Not yet implemented")
override fun containsValue(value: Any): Boolean = TODO("Not yet implemented")
override fun containsKey(key: String): Boolean = TODO("Not yet implemented")
override fun size(): Int = TODO("Not yet implemented")
}
e: file:///Users/robert/dev/myproject/src/main/java/example/Implementation.kt:12:3 Accidental override: The following declarations have the same JVM signature (size()I):
fun size(): Int defined in example.Implementation
fun size(): Int defined in example.Implementation
Rob Elliot
09/12/2024, 3:35 PMBut as usual, you can probably use @JvmName to fix the problem?I don't really understand how - since I'm implementing interfaces in compiled, 3rd party code, surely I have to have the correct JVM name?
Rob Elliot
09/12/2024, 3:37 PMRob Elliot
09/12/2024, 3:38 PM@JvmName
around, haven't found a form that fixes it.Rob Elliot
09/12/2024, 3:40 PMVampire
09/12/2024, 3:45 PMVampire
09/12/2024, 3:53 PM@JvmName("getTheSize")
on fun size()
to fix the problem.
But when the methods implements a Java interface, that does not work of course and you get "not applicable to this declaration"Vampire
09/12/2024, 3:55 PMval size
without implementing Map
also works.
So somehow if the val size
implements the Map.size
, a second size()
method is added, which cannot implement the Java size()
method though.
🙈Vampire
09/12/2024, 4:00 PMMap
interface:
// $FF: bridge method
public final int size() {
return this.getSize();
}
Vampire
09/12/2024, 4:18 PMjava.util.Map
has an int size()
method.
So for kotlin.collections.Map
being compiled to java.util.Map
, this bridge method is compiled in.
And that then conflicts with the size
method added additionally.Daniel Pitts
09/12/2024, 4:44 PMclass MyClass {
private inner class MapImpl : Map<X,Y> {
...
}
private inner class FooImpl : Foo {
}
val asMap: Map<X,Y> get() = MapImpl()
val asFoo: Foo = get() FooImpl()
}
This is actually somewhat better as a design principal anyway.