假设我有一个 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 pug
、val 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 final
Java 内部类中允许编译时常量字段),但它们的有用性将受到严重限制,它只是不是 Kotlin 语言规范的一部分。