Ruby中的作用域和java不太一样,它没类似java的内部作用域和嵌套作用域,在java中我们可能写出这样的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// outter.java
class Outter {
private String name = "我是Outter的name";

class Inner{
public void say(){
System.out.println(name);
}
}
}
// main.java
public class main {
public static void main(String[] args){
Outter outter = new Outter();
outter.new Inner().say(); // => 我是Outter的name
}
}

我们可以看到上面的Inner的内部类可以访问包裹类Outter的成员变量name,也就说在java中一个作用域可以看到外围作用域的变量。但在ruby这样写显然是不行的,不信?我们可以试试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Outter
def self.name
p @name
end
@name = "我是Outter的name"

class Inner
def say_outter
p name
end
end
end

Outter::Inner.new.say_outter
# => NameError: undefined local variable or method `name' for #<Outter::Inner:0x007fcf111e3a10

我们可以看到我们调用Inner的实例方法say_outterundefind local variable or method的错误。
这是因为在ruby中一个作用域和作用域内的之间是完全分开的(井水不犯河水)。当我们从一个作用域切换到另一个作用域,原先的绑定会被替换成一组新的绑定,我们可以利用Kernel#local_variables方法来验证这一问题。(local_variable方法会打印出当前绑定的名称)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
v1 = 1
class MyClass
v2 = 2
local_variables # => [:v2]

def my_method
v3 = 3
local_variables
end

local_variables # => [:v2]
end

obj = MyClass.new
obj.my_method # => [:v3]
obj.my_method # => [:v3]
local_variables # => [:v1, :obj]


ruby中在类定义模块定义方法定义的时候会切换作用域。