首页 > 代码库 > ruby中的作用域

ruby中的作用域

   作用域(scope)指的是变量的可达性或可见性。不同类型的变量有不同的作用域规则。与self类似,作用域在程序的执行过程中也在不断的变化,也可以根据上下文推断出"谁在什么作用域中"。但是,self和作用域不是同一个东西,在self没有变化的时候,可以开始一个新的局部作用域,有时候,作用域和self一起改变。

全局作用域和全局变量:全局变量最不常用,但需要了解。全局变量用$开始,在整个程序的任何位置都可以访问,穿过所有的边界。

局部作用域:在任意时刻,程序都处在一个特定的局部作用域中。两个作用域的主要区别就是可访问的局部变量不同。

ruby中辨别作用域的开始和结束:

  • 顶层有它自己的局部作用域
  • 每一个类或模块定义块(class,module)有它自己的局部作用域,即使是嵌套的类/模块定义块也一样。
  • 每一个方法定义(def)有它自己的局部作用域

如下:

1 class C2     a = 13     def local_a4         a = 25         p a6     end7     p a8 end9 C.new.local_a

输出1 2。

PS:每次使用关键字def,class,module引入一个定义块的时候,就开始了一个新的局部作用域。不论它们如何嵌套,都是这样的。这和c语言不一样,c语言中内部作用域可以看到外部作用域的变量,但是ruby中不能。

如下:

 1 class A 2     class B 3         a = 1 4         class C 5             a=2 6             p a 7         end 8         p a 9     end10 end

输出2 1

 

局部作用域和self

当定义一个块的时候,就开始了新的局部作用域,也开始了一个特定的self的代码,但self和作用域并不是完全平行的起作用。

  • 同样的self,不同的局部变量。
class C    def a        a = 1        p self        p a    endendc = C.newc.ac.a

两次调用了c.a,其中的self是一样的,但是a却是不一样的变量。

 

  • 不同的self,同样的局部变量  
 1 class A 2     p self                          3     var = "hello" 4     p var                      5     define_method :my_method do 6         p self                7         p var 8     end 9 end10 11 A.new.my_method

输出:

A
"hello"
#<A:0x1f08150>
"hello"

在这个函数里面,局部变量var是一样的,但是self却是不一样的,具体原因见下面的扁平化作用域。

 

常量的作用域和解析:

常量可定义在类或者模块里面,可以用相对路径或者绝对路径来访问。

 1 class A 2     X = 1 3     class B 4         Y = 2 5         class C 6             X = 3 7         end 8         p C::X 9     end10 end11 p A::X12 p A::B::Y13 p A::B::C::X

输出3 1 2 3

 

扁平化作用域:

       在进入另一个作用域的时候,局部变量立刻失效,那么如何让局部变量能在新的作用域里使用呢?替换关键字就是一个方法。

  class 替换成Class.new

  module替换成Module.new

  def替换成Module#define_method

如下:

1 var = "hello world"2 class A3     #在这里打印var4     def method5         #在这里打印var6     end7 end

假如想实现这个功能,让var能在这两个地方可见,可以用到扁平化作用域的知识。

如下:

1 var = "hello world"2 A = Class.new do3     p var4     define_method :method do5         p var6     end7 end8 A.new.method

输出两个hello world。

 

共享作用域:

假如你想在一组方法之间共享一个变量,但是有不希望其他方法可以访问这个变量,可以用到扁平作用域的方法

如下:

 1 def define_methods 2     shared = 0 3      4     Kernel.send :define_method,:counter do 5         shared 6     end 7      8     Kernel.send :define_method,:inc do |x| 9         shared += x10     end11 end12 13 define_methods14 p counter15 inc(3)16 p counter

输出0 3 。方法counter和inc之间会共享shared这个变量。