Kotlin for Android 和静态 final 内部类

6

我正在尝试使用Kotlin重写我的Android应用程序,并且在转换ContentProvider合同类时遇到了问题。 因此,我有一个简单的合同类(默认内容类型和内容URI之类的东西被省略):

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 中?

更新 我认为我应该澄清一下——我的调用者代码也是在 Kotlin 中。 问题出在 @JvmField 注释上。有了它,我可以直接访问静态成员,而不必调用 getter。


请提供一个 MCVE。我将您的 BirthdayContract 粘贴到了一个新的 Kotlin 文件中,并删除了其中的 : BaseColumns,因为它会导致编译错误。我还创建了一个函数来访问 BirthdayContract.Contacts.NAME。我认为您需要提供更多信息和/或更新的示例,以便演示您所遇到的问题。谢谢。 - mfulton26
@mfulton26 我也是这样做的——创建了一个新的 .kt 文件,并把我的 Kotlin 代码复制到里面。它编译时没有出现错误。BaseColumns 接口也没有问题。你遇到了什么样的错误? - noktigula
4个回答

6

NAME 是一个属性,它的备用字段默认是私有的。但由于它是一个属性,所以它有一个getter: getNAME()

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

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

@JvmField 对我很有效,谢谢!然而,“const”和“@JvmStatic”没有影响。 - noktigula

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注释。

0
考虑使用普通对象:
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互操作性,如果您计划全面使用Kotlin,则不需要它。


0

你可以使用 @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扩展它的原因。 - aldok

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接