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

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

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

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

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

如下:

 class C
a = 1
def local_a
a = 2
p a
end
p a
end
C.new.local_a

输出1 2。

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

如下:

 class A
class B
a = 1
class C
a=2
p a
end
p a
end
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,同样的局部变量
 class A
p self
var = "hello"
p var
define_method :my_method do
p self
p var
end
end A.new.my_method

输出:

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

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

常量的作用域和解析:

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

 class A
X = 1
class B
Y = 2
class C
X = 3
end
p C::X
end
end
p A::X
p A::B::Y
p A::B::C::X

输出3 1 2 3

扁平化作用域:

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

  class 替换成Class.new

  module替换成Module.new

  def替换成Module#define_method

如下:

 var = "hello world"
class A
#在这里打印var
def method
#在这里打印var
end
end

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

如下:

 var = "hello world"
A = Class.new do
p var
define_method :method do
p var
end
end
A.new.method

输出两个hello world。

共享作用域:

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

如下:

 def define_methods
shared = 0 Kernel.send :define_method,:counter do
shared
end Kernel.send :define_method,:inc do |x|
shared += x
end
end define_methods
p counter
inc(3)
p counter

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

ruby中的作用域的更多相关文章

  1. 理解Ruby中的作用域

    作用域对于Ruby以及其它编程语言都是一个需要理解的至关重要的基础知识.在我刚开始学习ruby的时候遇到很多诸如变量未定义.变量没有正确赋值之类的问题,归根结底是因为自己对于ruby作用域的了解不够, ...

  2. 谈谈Ruby中的类变量

    Ruby中的类变量,很多文章都是不太建议使用的,主要原因在于他的一些特性容易导致犯一些错误,尤其在广泛使用元编程的时候. 初步接触类变量可能觉得他跟C++的类静态成员和Java中的静态变量没什么区别, ...

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

    上一篇讲了ruby中的可调用对象proc和lambda,他们都是块转换成的对象.ruby中的可调用对象还有方法.通过使用method方法,并且以方法名作为参数(字符串或者符号),就可以得到一个方法对象 ...

  4. ruby中的可调用对象--proc和lamdba

    ruby中将块转变成对象的三种方法 ruby中的大部分东西都是对象,但是块不是.那么,如果你想存下来一个块,方便以后使用,你就需要一个对象.ruby中有三种方法,把块转换成可以利用的对象. Proc. ...

  5. Ruby 中的闭包-代码块

    看了一片文章https://ruby-china.org/topics/38385讲closure的. 写下一些感想: 闭包就是 一个函数能够记住和存取它的lexical作用域,即使这个函数是在它的l ...

  6. JavaScript中的作用域

    很多(JavaScript)开发者都在讨论"作用域",但它是什么?它们在JavaScript中的任何地方!我发现很多年轻的开发者不知道作用域是什么.他们中大多数人可以用jQuery ...

  7. [翻译]理解Ruby中的blocks,Procs和lambda

    原文出处:Understanding Ruby Blocks, Procs and Lambdas blocks,Procs和lambda(在编程领域被称为闭包)是Ruby中很强大的特性,也是最容易引 ...

  8. 探讨Nodejs中的作用域问题。

    在JS中有全局作用域和函数作用域,而在Nodejs中也自己的作用域,分为全局作用域(global)和模块作用域. js作用域: 以前学js的时候我们的全局对象是window,如: var a = 10 ...

  9. [No000010]Ruby 中一些百分号(%)的用法小结

    #Ruby 中一些百分号(%)的用法小结 #这篇文章主要介绍了Ruby 中一些百分号(%)的用法小结,需要的朋友可以参考下 what_frank_said = "Hello!"#% ...

随机推荐

  1. querySelectorAll 和getElementsByClassName的区别

    querySelectorAll 返回的是映射 改变其值不会改变document 而getElementsByClassName 改变它就会改变document 摘自JavaScript权威指南(jQ ...

  2. LR的响应时间与使用IE所感受时间不一致的讨论(摘抄补充)

    http://www.51testing.com/html/33/564333-865629.html 在做性能测试时,有时碰到这样一种情况,使用性能工具LR测试出来的响应时间比实际使用IE感受到的时 ...

  3. Android 模拟机出现Installation failed due to invalid URI!错误

    [2017-03-28 09:52:13 - DataVDemo06] Installation failed due to invalid URI![2017-03-28 09:52:13 - Da ...

  4. 过滤一个Collection最好的方法

    private static List<Integer> filter(List<Integer> list){ Iterator<Integer> it = li ...

  5. 【BZOJ2553】[BeiJing2011]禁忌 AC自动机+期望DP+矩阵乘法

    [BZOJ2553][BeiJing2011]禁忌 Description Magic Land上的人们总是提起那个传说:他们的祖先John在那个东方岛屿帮助Koishi与其姐姐Satori最终战平. ...

  6. 【BZOJ2982】combination Lucas定理

    [BZOJ2982]combination Description LMZ有n个不同的基友,他每天晚上要选m个进行[河蟹],而且要求每天晚上的选择都不一样.那么LMZ能够持续多少个这样的夜晚呢?当然, ...

  7. Java中break、continue、return语句的使用区别

    break.continue.return之间的区别与联系 在软件开发过程中,逻辑清晰是非常之重要的. 代码的规范也是非常重要的.往往细节决定成败.在编写代码的时候,一定要理解语言的作用以及使用的方法 ...

  8. Python--比较两个字典部分value是否相等

    # 比较两个字典部分是否相等def compare_two_dict(dict1, dict2, key_list): flag = True keys1 = dict1.keys() keys2 = ...

  9. Hibernate中的映射关系(一对多)

    在数据库中表和表之间的关系有几种,(一对一,一对多,多对多)一对一关系:可以选择任意一方插入外键(one-to-one:one-to-one<--->many-to-one[unique= ...

  10. Netty 粘包/半包原理与拆包实战

    Java NIO 粘包 拆包 (实战) - 史上最全解读 - 疯狂创客圈 - 博客园 https://www.cnblogs.com/crazymakercircle/p/9941658.html 本 ...