【问题标题】:Kotlin for android and static final inner classesKotlin for android 和 static final 内部类
【发布时间】:2016-12-02 01:37:57
【问题描述】:

我正在尝试在 Kotlin 上重写我的 android 应用程序,但在转换 ContentProvider 合同类时遇到了问题。 所以我有简单的合同类(内容类型和内容 uris 等默认内容被省略):

public final class Contract {
    public static final class Contacts {
        public static final String NAME = "Name"
        public static final String BIRTH = "Birth"
        public static final String IMAGE = "Image"
    }
}

如果我理解正确,在 Kotlin 中我们没有静态成员。取而代之的是,我们有“伴侣对象”。所以在将它转换为 Kotlin 之后,我有这个代码:

object BirthdayContract {
    class Contacts : BaseColumns {
        companion object {
            val NAME = "Name"
            val BIRTH = "Birth"
            val IMAGE = "Image"
        }
    }
}

但是,当我尝试访问 Contract.Contacts.NAME 等字段时,出现错误:“NAME 具有私人访问权限”。更改可见性修改器没有效果。 那么有没有办法在 Kotlin 中使用这样的契约类,或者最好将其保留在 Java 中?

UPD 我想我应该澄清一下——我的调用者代码也在 Kotlin 中。 问题出在@JvmField 注释中。有了它,我可以直接访问静态成员,而无需调用 getter。

【问题讨论】:

  • 请提供MCVE。我将您的 BirthdayContract 粘贴到一个新的 Kotlin 文件中,删除了 `:BaseColumns`,因为它不能使用它进行编译,并创建了一个访问 BirthdayContract.Contacts.NAME 的函数。我相信您需要提供更多信息和/或更新的示例来编译和演示您所看到的问题。谢谢。
  • @mfulton26 我做了同样的事情——创建了新的 .kt 文件,并在里面复制了我的 Kotlin 代码。它编译没有错误。 BaseColumns 界面没有问题。你有什么样的错误?

标签: java android kotlin


【解决方案1】:

NAME 是一个属性,默认情况下它的支持字段具有私有访问权限。但由于它是一个属性,所以它有一个吸气剂:getNAME()

由于这不是您在 Java 中自然访问常量的方式,因此有几种方法可以直接公开该字段:

  1. const: const val NAME = "Name"
  2. @JvmField 注释:@JvmField val NAME = "Name"

【讨论】:

  • @JvmField 很适合我,谢谢!但是,“const”和“@JvmStatic”不会影响任何东西。
【解决方案2】:

要将常量公开为字段,请使用 @JvmField 注释它们

class Contacts  {
    companion object {
        @JvmField val NAME = "Name"
        @JvmField val BIRTH = "Birth"
        @JvmField val IMAGE = "Image"
    }
}

然后你可以像这样在 Java 中使用它们:

String name = Contacts.NAME;

一旦您的所有代码都在 Kotlin 中,您就可以删除 @JvmField 注释。

【讨论】:

    【解决方案3】:

    你可以用 @JvmStatic 来做到这一点

    object BirthdayContract {
        class Contacts : BaseColumns {
            companion object {
                @JvmStatic val NAME = "Name"
                @JvmStatic val BIRTH = "Birth"
                @JvmStatic val IMAGE = "Image"
            }
        }
    }
    
    //Java
    BirthdayContract.Contacts.Companion.getNAME()
    

    到目前为止,我认为没有充分的理由扩展 BaseColumns,所以更好的选择应该是

    object BirthdayContract {
        object Contacts  {
               const val NAME = "Name"
               const val BIRTH = "Birth"
               const val IMAGE = "Image"
    
        }
    }
    //Java
    BirthdayContract.Contacts.NAME
    

    最重要的是,kotlin 中的嵌套对象看起来并不干净。 请考虑简化您的代码

    【讨论】:

    • BaseColumns 有 ID 和 COUNT,我认为这就是 noktigula 扩展它的原因。
    【解决方案4】:

    考虑使用普通的object。:

    object Contract {
        object Contacts {
            val NAME = "Name"
            val BIRTH = "Birth"
            val IMAGE = "Image"
        }
    }
    

    这应该可以完美地填充您的初始 Java 代码。

    在最新的稳定 Kotlin 版本中,public 是默认可见性。

    您可以选择为编译时常量添加 const 关键字,以便它们可以在注释中使用。:https://kotlinlang.org/docs/reference/properties.html#compile-time-constants

    @JvmStatic 注释适用于 Java-Interop,如果您打算使用完整的 kotlin,则不需要它。

    【讨论】:

      猜你喜欢
      • 2012-06-28
      • 1970-01-01
      • 2011-06-11
      • 1970-01-01
      • 1970-01-01
      • 2015-10-08
      • 2015-12-09
      • 1970-01-01
      相关资源
      最近更新 更多