【问题标题】:Implement (/inherit/~extend) annotation in Kotlin在 Kotlin 中实现 (/inherit/~extend) 注解
【发布时间】:2019-01-07 14:05:20
【问题描述】:

在 Java 中,我可以“实现”注释。

示例 Java 注释:

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

Java“实现”示例:

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 };
  }
}

尝试将其移植到 Kotlin 不起作用,因为它说注释是最终的,因此不能被继承,即以下内容不起作用:

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

您如何以 Kotlin 的方式“实现/扩展”注释?找不到 Kotlin 在这方面与 Java 不同的任何原因。欢迎任何提示如何解决该问题或任何说明为什么会这样的来源。

以下问题包含此星座的用例:Dynamically fire CDI event with qualifier with members。 基本上你需要这样的东西来缩小应该根据其成员触发的限定符。

请注意,这也适用于 Kotlin 注释,而且似乎 Kotlin 注释无法打开,因此也无法实现/扩展。

到目前为止,我发现@Inherited 是一个问题:

但我没有找到任何原因说明为什么注释不能像在 Java 中那样实现/继承。

我现在也在这里问过这个问题:https://discuss.kotlinlang.org/t/implement-inherit-extend-annotation-in-kotlin/8916

更新:最后我发现了有关此设计决策的一些信息,即以下问题(当我为此打开自己的问题时):Annotations inheritance. Either prohibit or implement correctly。看起来该决定是“禁止”它,即使没有(可见的?)cmets、讨论或其他有关该决定的消息来源。

新增以下问题:https://youtrack.jetbrains.com/issue/KT-25947

【问题讨论】:

  • 嗯。我从未见过一个班级尝试implements 一个注释,我什至没有意识到这是可能的。您几乎总是将注释应用到类。
  • 至少在Java中我已经看过好几次了。一个这样的例子是当您尝试select an instance in CDI 时,您通常使用AnnotationLiterals,它们基本上是注释的“实现”。但是,如果您需要提供 values 或您的注释具有的其他特定属性,您可能只需要这样的实现。
  • 你能指出我的实际代码吗?使用注解作为限定符通常不涉及实现它。
  • Here is an example question。基本上你需要这样的东西来缩小应该根据其成员触发的限定符。
  • 注解仍然是用 Java 编写的,但同样适用于 Kotlin 注解(您无法打开它)。

标签: java kotlin kotlin-interop


【解决方案1】:

从 Kotlin 1.3 开始,不支持这种情况。要创建注释的自定义实例,现在必须求助于 Java。做出此设计决策的原因之一是制作注释接口过于特定于 JVM,并且无法很好地映射到其他平台。

【讨论】:

  • 虽然我理解这个决定(并且 AnnotationLiteral 绝对是一个相当特殊的情况),但我也想知道 @JvmName 之类的东西已经 ;-) 是否有计划在 JVM 上仅使用 Kotlin 之类的东西(不需要@Jvm-annotations)?所以可能像:我 100% 确定(并且知道我在做什么)并且只想调用 Kotlin 和 Java 代码,但不希望能够从 Java 调用 Kotlin 代码(或者我不介意代码调用从 Java 看起来很难看,因为可能会生成方法名称)?
  • @Roland 我看不出你的问题与这里的主题有什么关系。此外,如果您不关心 Java API,我根本不明白为什么需要 @JvmName。让我们在别处讨论
  • 对不起.. 我刚刚从注释跳到“太 JVM-specific” 并提醒自己 name clashes requiring @JvmName 并写下了我想到的 ;-) 你是对的,这并不真正相关.. . 当然,我们要在哪里继续?
  • @Roland 我认为这对于我们的公共 Slack 或论坛来说是一个很好的讨论
猜你喜欢
  • 2020-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-11
  • 2023-03-24
  • 2014-11-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多