在Kotlin中,如果我在匿名对象上定义一个方法,有时我可以访问它,而其他时候则不能。这似乎与范围规则有关,但是我不确定是什么。
在下面的代码示例中,对example3.field.method()
的访问将导致编译错误。有趣的是,example2.field.method()
可以很好地编译。
以下行为的解释可能是什么?
class Example3 {
val field = object {
fun method() {}
}
}
fun showcase() {
val example1 = object {
fun method() {}
}
example1.method()
println(example1::class.qualifiedName)
class Example2 {
val field = object {
fun method() {}
}
}
val example2 = Example2()
example2.field.method()
println(example2::class.qualifiedName)
val example3 = Example3()
// example3.field.method() // won't compile
println(example3::class.qualifiedName)
}
答案 0 :(得分:5)
来自文档Object Expressions and Declarations:
请注意,匿名对象只能在本地和本地用作类型 私人声明。如果您使用匿名对象作为返回类型 公共职能或公共财产的类型,实际类型 该函数或属性的,将是的已声明超类型 匿名对象,或者
Any
(如果您未声明任何超类型)。 会员 添加到匿名对象中的对象将无法访问。
在下面的代码示例中演示:
class Example4{
val publicObj = object{
val x = 1
}
private val privateObj = object{
val x = 2
}
fun showcase(){
val scopedObj = object{
val x = 3
}
println(publicObj.x) // ERROR : unresolved reference: x
println(privateObj.x) // OK
println(scopedObj.x) // OK
}
}
答案 1 :(得分:2)
Pawel给出了正确的答案,指向文档:
该函数或属性的实际类型将是匿名对象的声明的超类型;如果未声明任何超类型,则为Any。
但是要补充一点,如果您确实需要访问example3.field.method()
,则可以在field
中为Example3
声明一个超类型:
interface MyInterface {
fun method()
}
class Example3 {
val field = object: MyInterface {
override fun method() {}
}
}
fun main() {
val example3 = Example3()
example3.field.method()
}