绑定

eval 方法可以接收可选的“绑定”(binding)参数,如果提供该参数,则使得执行计算在特定作用域或“上下文”(context)内完成。在 Ruby 中,发现绑定是 Binding 类的一个实例可能不会让人感到意外。你可以使用 binding 方法返回绑定。Ruby 类库中的 eval 文档提供了这个示例:

binding.rb
  1. def getBinding(str)
  2. return binding()
  3. end
  4. str = "hello"
  5. puts( eval( "str + ' Fred'" ) ) #=> "hello Fred"
  6. puts( eval( "str + ' Fred'", getBinding("bye") ) ) #=> "bye Fred"

这里的 binding 是 Kernel 的私有方法。getBinding 方法能够在当前上下文中调用 binding 并返回 str 的当前值。在第一次调用 eval 时,上下文是 main 对象,并使用局部变量 str 的值;在第二次调用中,上下文移动到了 getBinding 方法内,str 的局部值现在是方法的 str 参数。

上下文也可以由类定义。在 binding2.rb 中,你可以看到实例变量 @mystr 和类变量 @@x 的值根据类而不同:

binding2.rb
  1. class MyClass
  2. @@x = " x"
  3. def initialize(s)
  4. @mystr = s
  5. end
  6. def getBinding
  7. return binding()
  8. end
  9. end
  10. class MyOtherClass
  11. @@x = " y"
  12. def initialize(s)
  13. @mystr = s
  14. end
  15. def getBinding
  16. return binding()
  17. end
  18. end
  19. @mystr = self.inspect
  20. @@x = " some other value"
  21. ob1 = MyClass.new("ob1 string")
  22. ob2 = MyClass.new("ob2 string")
  23. ob3 = MyOtherClass.new("ob3 string")
  24. puts(eval("@mystr << @@x", ob1.getBinding)) #=> ob1 string x
  25. puts(eval("@mystr << @@x", ob2.getBinding)) #=> ob2 string x
  26. puts(eval("@mystr << @@x", ob3.getBinding)) #=> ob3 string y
  27. puts(eval("@mystr << @@x", binding)) #=> main some other value