Java 私有静态最终字段和匿名内部类与 Kotlin const val 和对象表达式/声明



假设我有一个 Kotlin 接口:

interface Dog {
fun walk()
}

我想通过稍作修改来创建此类的 Kotlin 对象,如下所示:

val poodle : Dog = object : Dog {
override fun walk() {
...
}
}

但是,我还想向这个对象添加一个相当于 Java 中的私有静态 final 字段的内容,如下所示(这是 Java 中的一个工作示例):

Dog poodle = new Dog() {
private static final String POODLE_FASHION = ...
@Override
public walk() {
...
}
}

我读到一个私人的 const val 相当于 Kotlin 中的这个。我尝试执行以下操作(这是 Kotlin 中不起作用的示例):

val poodle : Dog = object : Dog {
private const val POODLE_FASHION = ...
override fun walk() {
...
}
}

当我这样做时,我在Android Studio中收到以下错误:Const'val'只允许在顶层或对象中

有人可以解释为什么 Java 版本有效,而 Kotlin 版本不起作用吗?如何为 Kotlin 执行此操作(我已经尝试了同伴对象,但出现错误修饰符"同伴"不适用于"本地类")?注意我不想执行以下操作,因为我希望POODLE_FASHION生活在val poodle中,因为我将创建其他稍作修改的 Dog 对象(val pugval chihuahua等):

private const val POODLE_FASHION = ...
val poodle : Dog = object : Dog {
override fun walk() {
...
}
}

谢谢!

val poodle : Dog = object : Dog {
private const val POODLE_FASHION = ...
override fun walk() {
...
}
}

在这个例子中,真的没有任何理由需要静态或常量POODLE_FASHION。 它可以只是一个普通的val,它不会花费你任何额外的费用。

也就是说,听起来你应该有一个Poodle类,而不是一个对象。

请注意对象表达式和对象声明之间的区别。

  • val poodle = object: Dog { ... }是一个对象表达式。它创建一个匿名对象。这相当于用 Java 编写Dog poodle = new Dog() { ... }
  • object Poodle: Dog { ... }是一个对象声明。它创建一个单例对象,大致相当于创建一个仅限于只有一个实例的 Java 类。

Kotlin 文档指出,const val属性必须是"顶级,或对象声明或伴随对象的成员"。(https://kotlinlang.org/docs/reference/properties.html#compile-time-constants)。它们在对象表达式中无效。

以下对象声明应该可以正常工作:

object Poodle : Dog {
private const val POODLE_FASHION = ...
override fun walk() {
...
}
}

区分的一个重要原因是对象表达式不会声明新类型(尽管在 Java 术语中,它确实会导致匿名类)。

  • val poodle = object: Dog { ... }创建一个类型为Dog的变量。没有Poodle这样的类型.
  • object: Poodle: Dog { ... }创建一个类型为Poodle的对象。这是一种新类型,它是Dog的子类型。

这种差异很重要,因为在 Kotlin 中,const val属性始终属于一种类型。MyClass.MY_CONST_VAL是有效的,但按MyClass().MY_CONST_VAL访问它是一个错误,并且不起作用。因此,匿名对象上的const val属性将始终有效地私有于该对象。

我看不出为什么不可能允许匿名对象上的const val属性的技术原因(static finalJava 内部类中允许编译时常量字段),但它们的有用性将受到严重限制,它只是不是 Kotlin 语言规范的一部分。

最新更新