ruby具有在运行时执行以字符串形式保存的代码的功能设施,eval族方法 。包括Kernel#eval,Object#instance_eval,Module#class_eval。

  Kernel#eval

  它是最直接的方法

如下:

 p eval("2+2")

 eval("def m;p 'hello world';end")
eval("m")

输出

4
"hello world"

  eval强大而危险,有代码注入之类的危险,尽管ruby中有一个全局变量$SAFE来控制它,但最好还是不要用它。

  Object#instance_eval

  该方法将self变为instance_eval调用的接收者,对字符串或者代码块求值。

如下:

 p self

 a = []
a.instance_eval {p self}

输出

main
[]

  instance_eval常常用于访问其他对象的私有数据--特别是实例变量

如下:

 class C
def initialize
@x = 1
end
end c = C.new
c.instance_eval {puts @x}

输出

1

  instance_eval也可以接受字符串,访问局部变量。

如下:

 arr = ['a','b','c']
ch = 'd'
arr.instance_eval "self[1] = ch"
p arr

输出

["a", "d", "c"]

  

  instance_eval中定义方法,则会是个单例方法

如下: 

 obj = Object.new

 obj.instance_eval do
def method
p "hello world"
end
end
p obj.singleton_methods

输出

[:method]

  Module#class_eval

  class_eval和module_eval是一样的。它可以进入类定义体内。

 C = Class.new
C.class_eval do
def method
p "hello world"
end
end
c = C.new
c.method

输出

"hello world"

  

  class_eval可以做一些class关键字不能做的事

  1. 在类定义的上下文中对字符串求值
  2. 为匿名类(但不包含单例类)打开类定义(也就是说在不知道类的名字的情况就打开一个类)
  3. 获取外围作用域中变量的访问权
 def add_method_to(a_class)
a_class.class_eval do
def method ; p "hello world";end
end
end
add_method_to String
"abc".method

输出

"hello world"

 var = "hello world"

 class C
end
C.instance_eval {puts var}

输出

"hello world"

  

  总结:instance_eval()方法仅仅会改变self ,而 class_eval()会同时修改self和当前类,通过修改当前类,class_eval()实际上是重新打开了该类,就像class关键字一样。

  Module#class_eval()比class关键字更加灵活,class关键字只能使用常量,而class_eval()可以对任何代表类的变量使用class_eval()方法。class会打开一个新的作用域,但是class_eval()其实是扁平化作用域。

ruby中的instance_eval,class_eval,eval的更多相关文章

  1. ruby中的链式访问和方法嵌套

    先看一道题,这道题是codewars上的一道题,我很早就看到了,但是不会写.等到又看到这道题的时候,我刚看完元编程那本书,觉得是可以搞定它的时候了.废话不多说,先看这道题,题目最开始是为JavaScr ...

  2. 谈谈Ruby中的类变量

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

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

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

  4. 浅谈AngularJS中的$parse和$eval

    AngularJS的初学者常常会对$parse和$eval两个内建服务感到有些困惑,今天我们就来说说AngularJS中的$parse和$eval. 总的来说,$parse和$eval都是作用于Ang ...

  5. 理解Ruby中的作用域

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

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

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

  7. Ruby中 使用Builder Xml Markup 操作XML

    =begin Ruby中 使用Xml Markup 轻松的对XML文档操作, 项目地址:http://builder.rubyforge.org/ 使用之前我们需要安装Builder xml mark ...

  8. Ruby中Block, Proc, 和Lambda

    Block Blocks就是存放一些可以被执行的代码的块,通常用do...end 或者 {}表示 例如: [1, 2, 3].each do |num| puts num end [1, 2, 3]. ...

  9. ruby中symbol

    Symbol 是什么 Ruby 是一个强大的面向对象脚本语言(本文所用 Ruby 版本为1.8.6),在 Ruby 中 Symbol 表示“名字”,比如字符串的名字,标识符的名字. 创建一个 Symb ...

随机推荐

  1. VC中的学习点滴

    1.  __stdcall 和 __cdecl __cdecl 是C Declaration的缩写(declaration,声明),表示C语言默认的函数调用方法:所有参数从右到左依次入栈,由调用者负责 ...

  2. subprocess.Popen() 常用方法

    p.stdout.read() :用于读取标准输出,会一次性读取所有内容,返回一个字符串p.stdout.readline() :用于读取标准输出,一次只读取一行内容,返回一个字符串p.stdout. ...

  3. Vim相关优化和配置

    升级pythonwget https://www.python.org/ftp/python/3.6.5/Python-3.6.5.tgztar -xvf Python-3.6.5.tgzcd Pyt ...

  4. XStream中几个注解的含义和用法

    转自:http://blog.csdn.net/robert_mm/article/details/8459879 XStream是个很强大的工具,能将java对象和xml之间相互转化.xstream ...

  5. springmvc常用注解标签详解(转载)

    1.@Controller 在SpringMVC 中,控制器Controller 负责处理由DispatcherServlet 分发的请求,它把用户请求的数据经过业务处理层处理之后封装成一个Model ...

  6. 面试之一:CMS收集器整理

      CMS收集器整理 @white 基本说明: 目标:获取最短回收停顿时间 算法:标记-清除算法 线程:并发 步骤: 初始标记:(会STP) 标记 GC Roots 能直接关联到的对象,速度很快 并发 ...

  7. DELPHI中调用XSD去验证XML的合法性

    procedure TFrmPrintReport.Button3Click(Sender: TObject);var  SchemaDoc, XmlDoc: IXMLDOMDocument2;  S ...

  8. Tornado @tornado.gen.coroutine 与 yield

    在使用 Tornado 的过程中产生了以下疑问: 什么时候需要给函数增加 @tornado.gen.coroutine 什么时候调用函数需要 yield @tornado.gen.coroutine ...

  9. javaScript学习(4)框架学习

    javaScript学习4 1.框架 在一个普通HTML文档载入浏览器的同时还创建了一个模型,这个模型始于一个window对象和它包含的文档.单框架窗口和文档很很简单,window下就是documen ...

  10. TCP requires two packet transfers to set up the connection before it can send data

    wHTTP重用现存连接来减少TCP建立时延. HTTP The Definitive Guide 4.2.3 TCP Connection Handshake Delays When you set ...