eval
执行字符串中内容:eval("name") 会把name整个当做变量来处理,而不是说来eval一个“name”的字符串变量
指定binding中的字符串
#执行字符串,指定binding中的字符串
def get_binding(str)
return binding
end
str = "hello"
eval "str + ' Fred'" #=> "hello Fred" #就是执行字符串内容
eval "str + ' Fred'", get_binding("bye") #=> "bye Fred" #就是执行绑定中的字符串
instance_eval
#instance_eval,作用如下
1.改变对象的属性,因为执行的self是当前对象
2.绑定局部变量,并且改变局部变量的值
3.执行方法
4.定义单例方法,适用于类和对象,类和对象都是定义单例方法
5.执行字符串
#代码示例,改变对象的属性值,绑定局部变量
class MyClass
def initialize
@v = 1
end
end
v = 2
obj.instance_eval{
@v = v #改变对象的属性值,绑定局部变量
puts @v #=>2
}
#代码示例,利用instance_eval在对象中执行块和方法,这就是洁净室
class CleanRoom
def complex_calculation
11
end
def do_something
puts "do something"
end
end
clean_room = CleanRoom.new
clean_room.instance_eval do
if complex_calculation > 10
do_something
end
end
#类的单例方法
class Demo; end
Demo.instance_eval{def demo; "hello world"; end}
Demo.demo # "hello world"
Demo.new.demo #error
#实例的单例方法
class Demo; end
obj = Demo.new
obj.instance_eval{ def demo; "hello world"; end }
obj.demo #"hello world"
#执行代码字符串
array = ["a", "b", "c"]
x = "d"
array.instance_eval "self[1] = x"
puts array #=>["a","d","c"]
#使用块生成对象
class Widget
attr_accessor :name, :quantity
def initialize(&block)
instance_eval(&block) if block
end
end
obj = Widget.new do |widget|
widget.name = "jayzen"
widget.quantity = 0
end
p obj.name
p obj.quantity
class_eval
module_eval,这两个方法其实是别名
#只适用于类或模块,作用是打开类;class_eval和module_eval的执行功能是一致的
class Demo; end
Demo.class_eval{ def demo; "hello world"; end}
Demo.new.demo #"hello world"
Demo.demo # error
#执行字符串代码
class Demo; end
a = %q{ def demo; "hello world"; end }
Demo.module_eval(a)
Demo.new.demo #"hello world"
a = %q{hello world}
Demo.module_eval(a) #"hello world"
Demo.module_eval("\"hello\"") #"hello"
instance_exec
实例变量是基于当前调用的self对象,局部变量是基于当前的绑定
#instance_eval:该方法允许对块传入参数
class C
def initialize
@x = 1
end
end
class D
def twisted_method
@y = 2
C.new.instance_eval{ "@x: #{@x}, @y: #{@y}"} #允许对块传入参数,传递进来的实例变量是基于当前调用的self对象
end
end
D.new.twisted_method #=>"@x:1, @y: " #twisted_method方法的结果是C对象进行调用,传递进来的参数只能是@x,而不是@y
#instance_exec:避免instance_eval参数传递中出现的问题,使用instance_exec
class D
def twisted_method
@y=2
C.new.instance_exec(@y){|y| "@x: #{@x}, @y: #{y}"}
end
end
D.new.twisted_method #=> "@x:1, @y:2" #可以通过instance_exec方法实现参数传递,把@x和@y放在同一个作用域中
class_exec
module_exec
#class_exec和module_exec的功能是一致,相比class_eval和module_eval是可以传递参数
class Thing
end
obj = "hello"
Thing.class_exec(obj){|name|
puts name
} # "hello"