ruby中的作用域

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

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

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

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

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

如下:

1 class C
2     a = 1
3     def local_a
4         a = 2
5         p a
6     end
7     p a
8 end
9 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     end
10 end

输出2 1

 

局部作用域和self

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

  • 同样的self,不同的局部变量。
class C
    def a
        a = 1
        p self
        p a
    end
end
c = C.new
c.a
c.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 end
10 
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     end
10 end
11 p A::X
12 p A::B::Y
13 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 A
3     #在这里打印var
4     def method
5         #在这里打印var
6     end
7 end

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

如下:

1 var = "hello world"
2 A = Class.new do
3     p var
4     define_method :method do
5         p var
6     end
7 end
8 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 += x
10     end
11 end
12 
13 define_methods
14 p counter
15 inc(3)
16 p counter

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

 

posted @ 2014-07-27 15:24  smallbottle  阅读(358)  评论(0编辑  收藏  举报