嵌套/内部变量范围

mbr*_*ley 1 scope scala

有关Scala中变量的范围的确切处理是什么?

当我打开大括号时,我仍然可以访问外部变量的值(并在变量时修改它们):

scala> var mmm = 4
mmm: Int = 4

scala> {
     | println(mmm)
     | mmm += 2
     | println(mmm)
     | }
4
6

scala> println(mmm)
6
Run Code Online (Sandbox Code Playgroud)

但奥德斯基在第180页或他的书中说过

在Scala程序中,内部变量被称为遮蔽一个类似命名的外部变量,因为外部变量在内部范围内变得不可见.

这看起来更怪异:

scala> val a = 4
a: Int = 4

scala> {
     | println(a)
     | }
4
Run Code Online (Sandbox Code Playgroud)

那么我是否在内部范围内获得了它的副本?

scala> val a = 4
a: Int = 4

scala> {
     | val a = 8
     | }
Run Code Online (Sandbox Code Playgroud)

如果它不可变,我为什么还能再说val呢?

scala> val a = 4
a: Int = 4

scala> {
     | println(a)
     | val a = 8
     | println(a)
     | }
Run Code Online (Sandbox Code Playgroud)

但对于这个我得到一个错误:

error: forward reference extends over definition of value a
              println(a)
Run Code Online (Sandbox Code Playgroud)

Rex*_*err 5

如果在块中创建一个新的,则新的阴影会影响旧的(外部).如果你不这样做,你可以参考外面的那个.

块中创建新块的位置无关紧要; 如果它出现在任何地方,它会遮挡外部的一个.

所以,

val a = 5
{ println(a) }  // This is outer a

val a = 5
{ val a = 8; println(a) }  // This is inner a

val a = 5
{ println(a); val a = 8 }  // This is broken
                           // you try to print the inner a
                           // but it doesn't exist yet
Run Code Online (Sandbox Code Playgroud)

编辑:让我们解压缩最后一个

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!!!!
Run Code Online (Sandbox Code Playgroud)