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"

results matching ""

    No results matching ""