作用域(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. WebService的初级学习

    复习准备 1. Schema约束: 1.1   namespace相当于Schema文件的id: 1.2   targetNamespace属性用来指定schema文件的namespace的值; 1. ...

  2. insmod 内核模块参数传递

    对于如何向模块传递参数,Linux kernel 提供了一个简单的框架.其允许驱动程序声明参数,并且用户在系统启动或模块装载时为参数指定相应值,在驱动程序里,参数的用法如同全局变量. 通过宏modul ...

  3. 一道money计算题引发的思考

    网友提出一个问题如下 是小学和中学时候学到了增长折线问题,有点像数学问题,不过这个要求用编程来实现,恐怕还是有些逻辑要处理的,话不多说看代码吧 我给出的代码如下 代码清单: <?php func ...

  4. JSP内置对象——application,page,pageContext,config,Exception

    application对象application对象实现了用户数据的共享,可存放全局变量.application开始于服务器的启动,终止于服务器的关闭.在用户的前后链接或不同用户之间的连接中,可以对a ...

  5. URL中?和#的区别(关于SSRF)以及mysql的secure-file-priv

    零,绪论 20180125日,忙! 瞎比比总结一下,来满足这是个日记的样子. 1.今天谈的并不是什么技术[当然也不是没有技术(都很基础)]而是瞎几把扯. 一.关于一种SSRF的检测绕过: 1.背景: ...

  6. mac java环境

    1.java运行环境jre:http://www.java.com/zh_CN/ 2.jdk:http://www.oracle.com/technetwork/java/javase/downloa ...

  7. SignalR循序渐进(一)简单的聊天程序

    前阵子把玩了一下SignalR,起初以为只是个real-time的web通讯组件.研究了几天后发现,这玩意简直屌炸天,它完全就是个.net的双向异步通讯框架,用它能做很多不可思议的东西.它基于Owin ...

  8. git学习(5)分支管理(续)

    git学习(5)分支管理(续) 1.解决冲突 冲突的产生 如我们在新建分支和原来master分支上对同一文件做了修改并提交,在合并分支的时候就会遇到冲突 比如我新建了分支myBranch,在这个分支上 ...

  9. Netty处理TCP拆包、粘包

    Netty实践(二):TCP拆包.粘包问题-学海无涯 心境无限-51CTO博客 http://blog.51cto.com/zhangfengzhe/1890577 2017-01-09 21:56: ...

  10. JUnit4.12 源码分析之Statement

    1. Statement 抽象类Statement作为命令模式的Command,只有一个方法 各种Runner作为命令模式中的Invoker,将发出各种Statement,来表示它们运行JUnit测试 ...