【问题标题】:Companion Objects in Kotlin InterfacesKotlin 接口中的伴随对象
【发布时间】:2016-05-21 12:39:27
【问题描述】:

我正在尝试使接口 Parcelable,因此我需要这样的接口

interface AB : Parcelable {
    companion object {
        val CREATOR : Parcelable.Creator<AB>
    }
}

和我的两个班级 A 和 B 看起来像

data class A (...): Parcelable{
    ...
    companion object {
        val CREATOR : Parcelable.Creator<AB> = object : Parcelable.Creator<AB> {
            override fun newArray(size: Int): Array<AB?> {
                return arrayOfNulls(size)
            }

            override fun createFromParcel(parcel: Parcel): AB {
                return A(parcel)
            }

        }
    }

我正在努力在 kotlin 中实现这样的接口。似乎接口类不允许 CREATOR

也许我采取了错误的方法,
我有一个 parcelable,其中包含 A 或 B 类的列表 所以我在做

parcel.readTypedList(this.list, AB.CREATOR)

我要求列表是 A 或 B,这就是我使用接口的原因。

有人有任何建议或可能的解决方案吗?

【问题讨论】:

  • 如果您遇到特定的编译错误,请发布错误。
  • 感谢大家的帮助,我认为我没有很好地描述我的问题。无论如何,我通过遵循这个答案 stackoverflow.com/questions/22576709/… 并将 java 重写为 kotlin 解决了它。效果很好,只是我不再使用数据类。我试过 ParcelPaper,但它对我不起作用

标签: android parcelable kotlin


【解决方案1】:

在 Kotlin 中,接口可以有 companion object,但它不是必须由实现该接口的类实现的契约的一部分。它只是一个与具有一个单例实例的接口关联的对象。所以它是一个你可以存储东西的地方,但对实现类没有任何意义。

但是,您可以拥有一个由类的companion object 实现的接口。也许你想要更多这样的东西:

interface Behavior {
   fun makeName(): String
}

data class MyData(val data: String) {
    companion object: Behavior {  // interface used here
        override fun makeName(): String = "Fred"
    }
}

请注意,数据类没有实现接口,但它的companion object 实现了。

接口上的companion object 可用于存储与接口相关的常量或辅助函数,例如:

interface Redirector {
    fun redirectView(newView: String, redirectCode: Int)

    companion object {
        val REDIRECT_WITH_FOCUS = 5
        val REDIRECT_SILENT = 1
    }
}

// which then can be accessed as:
val code = Redirector.REDIRECT_WITH_FOCUS

【讨论】:

  • 过去,它被允许具有通用约束,例如“任何具有实现 Xyz 的伴随对象的类”,并且在早期的 Kotlin 中消失了,希望将来作为另一种类型重新出现的一般约束。然后你可以一般地谈论一个类和它的同伴。
  • 我想这仍然是 Kotlin 2017 年 4 月 13 日的情况?
  • @AdamHughes 您指的是包含伴随对象的通用约束吗?如果是这样,我认为他们还没有回来。
  • Jayson,我指的是专门将伴随对象放入接口中,正如您在此答案的最后一个代码 sn-p 中所示。
【解决方案2】:

通过convention,实现Parcelable 接口的类还必须有一个名为CREATOR 的非空静态字段,该字段的类型实现了Parcelable.Creator 接口。

您需要使用@JvmField 注释对CREATOR 属性进行注释,以将其公开为包含数据类的公共静态字段。

您还可以查看https://github.com/grandstaish/paperparcel — 一个注解处理器,它自动为 Kotlin 和 Java 生成类型安全的 Parcelable 包装器。

【讨论】:

  • 我认为您回答的第一部分没有帮助。第二部分本身就很有用。
  • @JaysonMinard 在这种情况下需要满足 Parcelable 约定,我编辑了答案来解释原因。
  • 非常感谢,在伴生对象中是否也需要JvmStaticJvmField
  • @JaysonMinard 不,JvmStatic 用于方法。这是最近在文档中排序的:kotlinlang.org/docs/reference/…
  • @JvmField 在接口的伴随对象中不起作用,所以看起来。有什么想法吗?
猜你喜欢
  • 2021-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-26
  • 2017-10-04
相关资源
最近更新 更多