【问题标题】:Kotlin data class implementing Java interfaceKotlin 数据类实现 Java 接口
【发布时间】:2016-06-08 11:06:27
【问题描述】:

我正在尝试将 Kotlin 引入我当前的项目中。我决定从实体开始,它似乎完美地映射到数据类。 例如我有一个数据类:

data class Video(val id: Long, val ownerId: Long, val title: String, val description: String? = null,
             val imgLink: String? = null, val created: Date? = null, val accessKey: String? = null,
             val views: Long? = null, val comments: Long? = null, val videoLink: String? = null): Entity

其中实现了Java接口:

public interface Entity {
   Long getId();  
}

但由于某种原因编译器不理解该方法已经实现:

类“视频”必须声明为抽象或实现抽象成员 public abstract fun getId(): kotlin.Long!在 net.alfad.data.Entity 中定义

我必须为 id 参数使用任何其他关键字吗? "!" 是什么意思签名中的意思?

【问题讨论】:

  • 签名中的 ! 表示这是一个平台类型,即来自 Java 的类型。你可以找到更多关于in the docs

标签: java overriding kotlin data-class


【解决方案1】:

这里的问题是 Kotlin 首先加载了 Java 类 Entity,它把 getId 看作一个函数,而不是某个属性的 getter。 Kotlin 类中的属性 getter 无法覆盖函数,因此属性 id 未绑定为 getId 函数的实现。

要解决此问题,您应该在 Kotlin 类中覆盖原始函数 getId。这样做会导致新函数与字节码中 id 的 getter 之间的 JVM 签名冲突,因此您还应该通过设置属性 private 来防止编译器生成 getter:

data class Video(
    private val id: Long,
    ...
): Entity {
    override fun getId() = id

    ...
}

请注意,此答案已从此处改编:https://stackoverflow.com/a/32971284/288456

【讨论】:

  • 不错的答案!还有一件事:这是否意味着 getter/setter 不是 Java 中的常规方法?
  • 在生成的字节码中,从 Java 的角度来看,它们是相同的。属性 getter 被编译为名为 getXxx 的方法。但是对于 Kotlin(1.0.0 版),属性访问器和函数是不同的,不能在层次结构中混合使用两者。
  • 有关于改变这个的讨论吗?这有什么理由不应该只是工作
  • an issue here。问题之一是您不能在 Kotlin 中用 fun getX 覆盖 val x 或反之亦然(按设计),因此如果您有 Kotlin 和 Java 代码的混合层次结构,则会出现各种复杂的问题,其中一些类使用属性和一些 -- 函数。
【解决方案2】:

如果这是您的整个数据类,那么您没有覆盖 getId()。我看到您有一个名为 id 的属性,Kotlin 应该为此生成一个 getter,但不会用您需要指示您正在覆盖抽象函数的 override 关键字标记。

-- 编辑-- 亚历山大打败了我!反正他的回答更好! ;)

【讨论】:

    猜你喜欢
    • 2018-01-29
    • 2021-01-29
    • 1970-01-01
    • 2019-12-26
    • 2017-12-30
    • 1970-01-01
    • 2018-05-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多