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.ImplementationRob 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.