Scala 变量的嵌套/内部范围
Scala中变量的作用域具体是什么 当我打开花括号时,我仍然可以访问外部变量的值(如果变量为,则修改它们): 但是奥德斯基在他的书第180页上说 在Scala程序中,内部变量被称为与外部变量类似的阴影, 因为外部变量在内部范围内不可见 这似乎更奇怪:Scala 变量的嵌套/内部范围,scala,scope,Scala,Scope,Scala中变量的作用域具体是什么 当我打开花括号时,我仍然可以访问外部变量的值(如果变量为,则修改它们): 但是奥德斯基在他的书第180页上说 在Scala程序中,内部变量被称为与外部变量类似的阴影, 因为外部变量在内部范围内不可见 这似乎更奇怪: scala> val a = 4 a: Int = 4 scala> { | println(a) | } 4 那么我要在内部范围中创建它的副本吗 scala> val a = 4 a: Int = 4
scala> val a = 4
a: Int = 4
scala> {
| println(a)
| }
4
那么我要在内部范围中创建它的副本吗
scala> val a = 4
a: Int = 4
scala> {
| val a = 8
| }
如果val是不可变的,为什么还要再说一遍
scala> val a = 4
a: Int = 4
scala> {
| println(a)
| val a = 8
| println(a)
| }
但对于这个,我得到了一个错误:
error: forward reference extends over definition of value a
println(a)
块本身不会更改外部变量的可见性。仅当在内部范围内声明具有相同名称的变量时,如Odersky引号所述 您的前两个示例没有做到这一点,因此外部变量在内部范围内清晰可见,而Odersky的引用不适用。内部范围中的
a
与外部范围中的a
相同,不涉及复制
然而,在第三个示例中,两个a
s是两个独立的val
变量,即内部a
并没有重新定义外部a
,只是根据奥德斯基的引文将其隐藏,例如:
val a = 4
println(a) // prints 4 - outer a
{
val a = 8;
println(a) // prints 8 - inner a
}
println(a) // prints 4 - outer a in scope again
即,退出内部块后,您会看到外部a
及其原始值仍然存在
但是,第三个示例中显示的代码非常模糊,因为如果不深入了解语言规范,就很难确定第一个
println(a)
语句所引用的变量。我手头没有确切的参考资料,但我相信编译器不允许这样的代码,因为这种风格本身就容易出错,但却没有任何好处。块本身不会改变外部变量的可见性。仅当在内部范围内声明具有相同名称的变量时,如Odersky引号所述
您的前两个示例没有做到这一点,因此外部变量在内部范围内清晰可见,而Odersky的引用不适用。内部范围中的a
与外部范围中的a
相同,不涉及复制
然而,在第三个示例中,两个a
s是两个独立的val
变量,即内部a
并没有重新定义外部a
,只是根据奥德斯基的引文将其隐藏,例如:
val a = 4
println(a) // prints 4 - outer a
{
val a = 8;
println(a) // prints 8 - inner a
}
println(a) // prints 4 - outer a in scope again
即,退出内部块后,您会看到外部a
及其原始值仍然存在
但是,第三个示例中显示的代码非常模糊,因为如果不深入了解语言规范,就很难确定第一个
println(a)
语句所引用的变量。我手头没有确切的参考资料,但我相信编译器不允许这样的代码,因为这种风格本身就容易出错,但却没有任何好处。如果在块中创建一个新代码,则新代码会与旧(外部)代码产生阴影。如果你没有,你指的是外面的那个
在块中的何处创建新块并不重要;如果它出现在任何地方,它会遮挡外部的一个
所以
编辑:让我们打开最后一个
val a = 5
// Okay, I have something called a
{ // Oh, new block beginning! Maybe there are local variables
println(a)
val a = 8 // Yeah, there's one!
// And it's got the same name as the outer one
// Oh well, who needs the outer one anyway?
}
// Waitaminute, what was that block supposed to do?
{
println(a) // Inner block has an a, so this must be the inner a
val a = 8 // Which is 8
}
// Hang on, operations happen in order
{
println(a) // What inner a?!
// Abort, abort, abort!!!!
如果在块中创建一个新的块,则新的块将遮挡旧的(外部)块。如果你没有,你指的是外面的那个 在块中的何处创建新块并不重要;如果它出现在任何地方,它会遮挡外部的一个 所以
编辑:让我们打开最后一个
val a = 5
// Okay, I have something called a
{ // Oh, new block beginning! Maybe there are local variables
println(a)
val a = 8 // Yeah, there's one!
// And it's got the same name as the outer one
// Oh well, who needs the outer one anyway?
}
// Waitaminute, what was that block supposed to do?
{
println(a) // Inner block has an a, so this must be the inner a
val a = 8 // Which is 8
}
// Hang on, operations happen in order
{
println(a) // What inner a?!
// Abort, abort, abort!!!!
我仍然很困惑,我只是无法理解这一点(我想这是我的错):现在我知道外壳是不同的,但我可以理解它是如何工作的,比如:martin@mintbox~$
a=5martin@mintbox~$(echo$a;a=8;echo$a)5 8martin@mintbox~$echo$a 5
在那里我可以看到创建的范围(对于var的副本,子shell不能影响外部变量的val,但是内部副本可以影响外部变量的val,但是您如何解释我的第一个示例,其中内部增量改变外部值?@mbrambley-内部增量是外部值的增量。您不会因为打开一些大括号而丢弃所有变量。这就像子shell一样在这方面进行分类:子对象仍然可以访问父对象中的所有内容,但可以添加自己的内容(或替换父对象的内容)。它实际上不是子类化,但这可能有助于您了解发生了什么。@mbrambley-是的,它会在执行任何操作之前扫描变量。(这是您可以在块的更下方引用def
的方式。)我不确定到底有多少个过程。我在编译时注意到至少三个明显的过程。谢谢,我想我现在明白了-我想我会在内部作用域中避免使用同名的变量,直到我能想到它们的用法…现在我害怕自己的阴影,但是变量呢?如果我分配它们,变化会在外部可见吗?我的sim卡ilar(我猜)代码不起作用:var finalWorld:WorldModel=null LifeActors.run(world,new WorldModelListener{override def worldUpdated(world:WorldModel)={finalWorld=world},3)//3次迭代val-alive=finalWorld.getElements.filter(u.isAlive).该死,我不知道如何在这里粘贴代码,对不起,我仍然很困惑,我只是无法理解这一点(我想这是我的错):现在我知道外壳不同了,但我可以理解它是如何工作的,比如:martin@mintbox~$a=5martin@mintbox~$(echo$a;a=8;echo$a) 5 8 martin@mintbox~$echo$a 5
在那里我可以看到创建的范围(对于var的副本,子shell不能影响外部变量的val,但是内部副本可以影响外部变量的val,但是您如何解释我的第一个示例,其中内部增量改变外部值?@mbrambley-内部增量是外部值的增量。您不会因为打开一些大括号而丢弃所有变量。这就像子shell一样在这方面分类: