假设我有一个Kotlin界面:
interface Dog {
fun walk()
}
我想创建一个Kotlin object of this class with slight modifications,就像这样:
val poodle : Dog = object : Dog {
override fun walk() {
...
}
}
但是,我还想向此对象添加一个等效于Java中的私有static final字段的东西,就像这样(这是Java中的一个有效示例):
Dog poodle = new Dog() {
private static final String POODLE_FASHION = ...
@Override
public walk() {
...
}
}
我读到私有常量在Kotlin中与此等效。我尝试执行以下(这是Kotlin中无法正常工作的示例):
val poodle : Dog = object : Dog {
private const val POODLE_FASHION = ...
override fun walk() {
...
}
}
这样做时,我在Android Studio中遇到以下错误:仅在顶层或对象中允许使用常量“ val” 。
有人可以解释为什么Java版本有效,但Kotlin版本无效吗?如何为Kotlin做到这一点(我已经尝试了伴侣对象,但收到错误修饰符“ companion”不适用于“本地类” )?请注意,我不想执行以下操作,因为我希望POODLE_FASHION
位于val poodle
内部,因为我还要创建其他经过稍微修改的Dog对象(val pug
,{{1 }}等)
val chihuahua
谢谢!
答案 0 :(得分:1)
val poodle : Dog = object : Dog {
private const val POODLE_FASHION = ...
override fun walk() {
...
}
}
在此示例中,根本没有任何理由POODLE_FASHION
必须是静态或常量。它可以只是普通的val
,而且不会花任何额外费用。
也就是说,听起来您应该拥有Poodle
类,而不是对象。
答案 1 :(得分:0)
请注意对象表达式和对象声明之间的区别。
val poodle = object: Dog { ... }
是object expression。它创建一个匿名对象。相当于用Java编写Dog poodle = new Dog() { ... }
。object Poodle: Dog { ... }
是object declaration。它创建一个单例对象,大致等效于创建一个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
属性(Java内部类中允许使用static final
编译时常量字段),但是它们的实用性将受到严格限制,而这并不是Kotlin语言规范的一部分。