msrd0
msrd0

Reputation: 8371

Java Interop: Apply @JvmName to getters of properties in interface or abstract class

Usually, we can write the following code in kotlin:

val hasValue : Boolean
    @JvmName("hasValue") get() = true

This will generate the method hasValue() instead of getHasValue() for Java interop.

However, in an interface, this gives me a compile error:

val hasValue : Boolean
   @JvmName("hasValue") get

The same goes for the following declaration in an abstract class:

abstract val hasValue : Boolean
    @JvmName("hasValue") get

So here is my question: How can I tell the kotlin compiler to use hasValue() instead of getHasValue() for getters (and setters) of properties in a kotlin interfaces?

Upvotes: 28

Views: 7064

Answers (3)

Nikita Bobko
Nikita Bobko

Reputation: 624

There is a workaround, see: https://youtrack.jetbrains.com/issue/KT-31420

Simply suppress this INAPPLICABLE_JVM_NAME error with annotation: @Suppress("INAPPLICABLE_JVM_NAME")

Upvotes: 25

retodaredevil
retodaredevil

Reputation: 1382

I turns out, this is possible:

interface Foo {
    val bar: String
        @get:JvmName("getAwesomeBar") get
}

However, it is interesting that this does NOT work:

interface Foo {
    @get:JvmName("getAwesomeBar") 
    val bar: String
}

But, this does work:

class Foo {
    val bar: String
        @JvmName("getAwesomeBar") get() = "My bar value"
}

and this works too!

class Foo {
    @get:JvmName("getAwesomeBar") 
    val bar: String
        get() = "My bar value"
}

Why you need to have the extra get: when doing this in interfaces is beyond me. I'm sure there is a reason for it.

Upvotes: 6

Jacky Choi
Jacky Choi

Reputation: 556

I think Kotlin has some restriction on using @JvmName on open/override property/function. Prohibiting the use of @JvmName on open/override function can avoid having different jvmName on the interface/superclass and subclass.

In the following example, I am trying to annotate the overrided property getter with a jvmName (hasValueImpl) which is different from the interface (hasValue) and it gives compilation error:

'@JvmName' annotation is not applicable to this declaration

interface Abstract {

    @get:JvmName("hasValue")        //Compile error
    val hasValue: Boolean
        get() = false
}

open class Impl : Abstract {

    @get:JvmName("hasValueImpl")    //Compile error
    final override val hasValue: Boolean
        get() = false

    @get:JvmName("hasValue2")       //Compile error if hasValue2 is open
    val hasValue2: Boolean
        get() = false
}

Upvotes: 12

Related Questions