Scala变量解析疑问:类变量与局部变量的作用域冲突问题
Scala局部变量遮蔽与作用域解析问题
先看你写的代码:
class A { val x = 0 def foo(): Unit = { println(x) // Error: x is a forward reference extending over the definition of x val x = 0 println(x) } }
为什么第一个println(x)不会解析为类成员变量x?
这是Scala的作用域遮蔽规则导致的:只要你在局部作用域(比如foo方法)里定义了同名变量x,整个局部作用域内的x都会被这个局部变量“抢走”绑定关系,哪怕局部变量是在后面才定义的。Scala编译时会先扫描整个方法的作用域,一旦发现有局部的x定义,就不会再去外层(类的成员域)找同名的x了。
局部变量是否会被提升至整个局部作用域?
Scala里没有像JavaScript中var那样的变量提升,但它会做作用域预解析:编译阶段会先遍历整个局部作用域,把所有变量的名字先绑定到对应的局部定义上。所以虽然局部x是在println之后才初始化的,但Scala已经认定这个println里的x就是那个还没完成定义的局部变量,而局部val在初始化前是不能被引用的,因此就抛出了“forward reference”(提前引用)的错误。
修复方案
如果想在第一个println里引用类成员的x,可以明确指定this.x,或者把局部变量改个名字,比如:
class A { val x = 0 def foo(): Unit = { println(this.x) // 明确指向类成员x,输出0 val localX = 0 println(localX) // 输出0 } }
内容的提问来源于stack exchange,提问作者Wickoo
相关产品推荐
相关产品推荐

