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这个变量。

ruby中的作用域

时间: 2024-10-17 00:21:39

ruby中的作用域的相关文章

理解Ruby中的作用域

作用域对于Ruby以及其它编程语言都是一个需要理解的至关重要的基础知识.在我刚开始学习ruby的时候遇到很多诸如变量未定义.变量没有正确赋值之类的问题,归根结底是因为自己对于ruby作用域的了解不够,但在你看看完我的这篇文章后,相信你不会再担心会遇到这些头疼的问题. 什么是作用域? 当谈论到作用域的时候,应该马上想到变量和可见性这两个词,变量和可见性是作用域的主要内容,没错,作用域就是关于在代码的什么地方什么变量是可见的,当你充分了解了作用域后,给你一段代码,你可以轻易知道此时什么变量是可见的,

ruby中的作用域和代码块

ruby中没有嵌套的作用域,它的作用域之间是分开的,一旦进入一个新作用域,原先的绑定就会被替换为一组新的绑定. 作用域门 一般来说,程序会在三个地方关闭前一个作用域,同时找开一个新的作用域. 它们分别是:class.module.def,它们被称为作用域门.class/module与def还有一点微妙的差别.在类或module中的代码会被立即执行.相反,方法中的代码只有在方法被调用的时候才执行. 扁平化作用域 my_var = "abc" class MyClass def my_me

谈谈Ruby中的类变量

Ruby中的类变量,很多文章都是不太建议使用的,主要原因在于他的一些特性容易导致犯一些错误,尤其在广泛使用元编程的时候. 初步接触类变量可能觉得他跟C++的类静态成员和Java中的静态变量没什么区别,但在实际使用中一不留神就会掉到类变量的陷阱中去 陷阱1,类变量跟类实例变量不同,类实例变量关联的是self,但类变量关联的是当前类作用域 class C end class D end class C @@var = "C" def D.getvar @@var end end class

ruby中的instance_eval,class_eval,eval

ruby具有在运行时执行以字符串形式保存的代码的功能设施,eval族方法 .包括Kernel#eval,Object#instance_eval,Module#class_eval. Kernel#eval 它是最直接的方法 如下: 1 p eval("2+2") 2 3 eval("def m;p 'hello world';end") 4 eval("m") 输出 4"hello world" eval强大而危险,有代码注

ruby中的可调用对象--方法

上一篇讲了ruby中的可调用对象proc和lambda,他们都是块转换成的对象.ruby中的可调用对象还有方法.通过使用method方法,并且以方法名作为参数(字符串或者符号),就可以得到一个方法对象. 如下: 1 class C 2 def talk 3 p "hello world" 4 end 5 end 6 7 c = C.new 8 meth = c.method :talk 9 meth.call 输出: "hello world" 类C有个实例方法ta

Ruby 中的闭包-代码块

看了一片文章https://ruby-china.org/topics/38385讲closure的. 写下一些感想: 闭包就是 一个函数能够记住和存取它的lexical作用域,即使这个函数是在它的lexical作用域的外面执行. 当一个函数被写出来时,这个函数的closure就已经确定了. javascript中有闭包的概念:https://www.cnblogs.com/chentianwei/p/9739714.html Ruby中的关键字定义def是没有闭包的.它创建一个封闭的作用域.

聊一下JS中的作用域scope和闭包closure

scope和closure是javascript中两个非常关键的概念,前者JS用多了还比较好理解,closure就不一样了.我就被这个概念困扰了很久,无论看别人如何解释,就是不通.不过理越辩越明,代码写的多了,小程序测试的多了,再回过头看看别人写的帖子,也就渐渐明白了闭包的含义了.咱不是啥大牛,所以不搞的那么专业了,唯一的想法就是试图让你明白什么是作用域,什么是闭包.如果看了这个帖子你还不明白,那么多写个把月代码回过头再看,相信你一定会有收获:如果看这个帖子让你收获到了一些东西,告诉我,还是非常

(补充1)Ruby中的p、puts、print对比

p 和 puts 是 Ruby 中特别常用的方法,很多童鞋可能认为它们是差不多的,使用的时候也不加注意,但是仔细考究起来,它们是有明显差别的. 先举一个例子: class Foo def inspect "foo from inspect" end def to_s "foo from to_s" endendfoo = Foo.newp fooputs foop "p: <#{foo}>"puts "puts: <#

javascript中函数作用域之”提升“

javascript中函数作用域之变量提升 当我们在函数内部用关键字var声明一个变量的时候,此变量的作用域限制在当前函数. 提升:在一个作用域内部,不管一个变量用var声明的位置在哪里,这个变量属于当前整个作用域,并且在当前作用域的任何位置都可以访问它.在javascript中,这种行为/现象称之为"提升",即一个变量在一个作用域的任何位置用var声明,javascript引擎都会把这些用var声明的变量"移动"到当前作用域的开始处. 谈到javascript这种