您的位置:首页 > 编程语言 > Ruby

ruby中的instance_eval,class_eval,eval

2014-07-31 15:53 501 查看
   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关键字不能做的事

在类定义的上下文中对字符串求值

为匿名类(但不包含单例类)打开类定义(也就是说在不知道类的名字的情况就打开一个类)

获取外围作用域中变量的访问权

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()其实是扁平化作用域。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: