为什么下面的代码会打印0
?
class X {
fun f() {
val x = 0
val a = object {
val x = 1
fun g() {
println(x)
}
}
a.g()
}
}
fun main() {
val x = X()
x.f()
}
为什么内部属性声明不会遮蔽外部属性声明?
最佳答案
1
对于非限定名称,本地可调用(即域内的声明)始终优先于非本地可调用。“内部作用域中的内容隐藏外部作用域中的内容”规则紧随其后。
从规范的
对于名为的标识符,
f
将分析以下集合(按给定的顺序):
f
当前范围及其向上链接范围中命名的本地非扩展可调用函数,按范围的大小排序(从小到大),不包括包范围;- 按照接收器优先级的顺序
e
,对d
当前范围内可用的每对隐式接收器的过载候选集进行计算,就好像是显式接收器一样;e
- [与本场景无关]
步骤 1 考虑所有本地可调用函数,然后我们才会在第二步中尝试使用接收器的可调用函数。
将其应用到您的代码中,
fun f() {
val x = 0 // This 'x' is local to 'f'
val a = object {
val x = 1 // This 'x' is not local. The body of an object literal is a declaration scope, not a statement scope
fun g() {
println(x)
}
}
a.g()
}
x
如果不像这样优先考虑当地人,那么当你在 时,你就无法提到当地人g
。
7
-
他们选择这样的作用域规则有什么原因吗?对于块状词法作用域来说,这是违反直觉的,你会期望内部事物掩盖外部事物。
–
-
@Wickoo 如果
x
本身访问对象的属性,那么您将如何访问主体中的x
本地?您可能会发明一些新的语法并引入更多复杂性,但如果引用本地,则没有必要,因为您已经可以使用 引用对象的属性。f
g
x
x
this.x
–
-
我猜这正是 Kotlin 设计师面临的问题。我会让
x
其绑定字段,而不是让其访问外部字段。x
在 Java 中,您如何访问外部字段?“` void f() { int x = 0; class A { int x = 1; void g() { System.out.println(x); } } A a = new A(); ag(); }“`
– -
@Wickoo 我不认为你能用 Java 做到这一点…这就是为什么 Kotlin 更好:)
– -
2@Wickoo 不,非限定名称首先针对本地进行解析。如果没有匹配,请尝试隐式接收器(即 implied
this
)。本地是在语句范围(可以放置语句的范围,如for
循环)中声明的内容。
–
|
|