Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implement (/inherit/~extend) annotation in Kotlin

In Java I have the possibility to "implement" annotations.

Sample Java annotation:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface JavaClassAnno {
  String[] value();
}

Sample Java "implementation":

class MyAnnotationLiteral 
                  extends AnnotationLiteral<JavaClassAnno> 
                  implements JavaClassAnno { // <--- works in Java
  private String value;

  public MyAnnotationLiteral(String value) {
    this.value = value;
  }
  @Override
  public String[] value() {
    return new String[] { value };
  }
}

Trying to port that to Kotlin doesn't work as it says that the annotation is final and therefore can not be inherited, i.e. the following will not work:

class MyAnnotationLiteral(private val internalValue: String) 
                 : AnnotationLiteral<JavaClassAnno>(), 
                   JavaClassAnno { // <--- doesn't work in Kotlin (annotation can not be inherited)
  override fun value(): Array<String> {
    return arrayOf(internalValue)
  }
}

How do you "implement/extend" annotations the Kotlin way? Could not find any reason why Kotlin differs in that regard to Java. Any hint how to solve that problem or any sources that tell why it is that way are welcome.

The following question contains a use case for this constellation: Dynamically fire CDI event with qualifier with members. Basically you require something like this to narrow down which qualifier should trigger based on its members.

Note that this would also apply to a Kotlin annotation as well as it seems that a Kotlin annotation can not be open and therefore not be implemented/extended too.

What I found so far is rather mentioning @Inherited as a problem:

  • https://discuss.kotlinlang.org/t/inherited-annotations-and-other-reflections-enchancements/6209
  • https://youtrack.jetbrains.com/issue/KT-22265

But I did not find any reason why the annotation is not implementable/inheritable as it is in Java.

I also asked this question now here: https://discuss.kotlinlang.org/t/implement-inherit-extend-annotation-in-kotlin/8916

Update: Finally I found something regarding this design decision, namely the following issue (while I was opening my own issue for it): Annotations inheritance. Either prohibit or implement correctly. As it seems the decision was to "prohibit" it, even though there are no (visible?) comments, discussions or other sources about that decision.

Added the following issue: https://youtrack.jetbrains.com/issue/KT-25947

like image 381
Roland Avatar asked Jul 31 '18 08:07

Roland


1 Answers

As of Kotlin 1.3, this case is not supported. To create custom instances of annotations one has to resort to Java for now. One of the reasons for this design decision is that making annotations interfaces is too JVM-specific and wouldn't map well to other platforms.

like image 54
Andrey Breslav Avatar answered Sep 28 '22 12:09

Andrey Breslav