Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 936
msrd0 Avatar asked Nov 27 '17 05:11

msrd0


People also ask

What is the nature of interface in Java?

All methods of interface are abstract and public in nature. The class which implements interface need to provide functionality for the methods declare in the interface. One can use interface to implement PM (Partial multiple inheritance) and DMD (Dynamic memory dispatch). Interface always implements in derived class.

Is setnumber part of myinterface in Java?

As you can see, only setNumber is part of MyInterface. Consumers do not need to know about how the number is stored, therefore it is an implementation detail. Besides, in Java you name classes and interfaces in PascalCase rather than camelCase.

What is the difference between interface and abstract class in Java?

Interface contains only abstract methods that can’t be instantiated and it is declared by keyword interface. A class that is declared with the abstract keyword is known as an abstract class in Java.

How JVM works – JVM architecture?

How JVM Works – JVM Architecture? In C++, if a class has at least one pure virtual function, then the class becomes abstract. Unlike C++, in Java, a separate keyword abstract is used to make a class abstract. Following are some important observations about abstract classes in Java. An instance of an abstract class can not be created.


3 Answers

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")

like image 173
Nikita Bobko Avatar answered Sep 23 '22 21:09

Nikita Bobko


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 } 
like image 44
Jacky Choi Avatar answered Sep 23 '22 21:09

Jacky Choi


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.

like image 44
retodaredevil Avatar answered Sep 21 '22 21:09

retodaredevil