Ruby 为什么instance_exec和class_exec有这种不同的行为?

Ruby 为什么instance_exec和class_exec有这种不同的行为?,ruby,metaprogramming,Ruby,Metaprogramming,我从instance\u exec class KlassWithSecret def initialize @secret = 99 end end k = KlassWithSecret.new k.instance_exec(5) {|x| @secret+x } #=> 104 我对instance_exec为什么这样做的理解是在下图中,它在其singleton类中添加了@secret+5 +------------------

我从
instance\u exec

  class KlassWithSecret
    def initialize
      @secret = 99
    end
  end
  k = KlassWithSecret.new
  k.instance_exec(5) {|x| @secret+x }   #=> 104
我对instance_exec为什么这样做的理解是在下图中,它在其singleton类中添加了@secret+5

  +-----------------------+
  |   singleton class do  |
  |     def method1       |
  |     ...               |
  |     end               |
  |     ...               |
  |     @secret + 5       |
  |   end                 |
  |                       |
  |                       |
  +-----------+-----------+
              |
    +---------+-------+
    |  instance k     |
    |   @secret       |
    |                 |
    +-----------------+
因此,我提出了使用类_exec获得相同结果的代码

k.singleton_class.class_exec(5) {|x| @secret + x}
它给了我一个@secret is nil error,我想知道为什么会这样,以及我的理解有什么问题

更新:


我注意到k.instance_exec{binding}和k.singleton_class.class_exec{binding}具有不同的绑定对象,因此它们必须是不同的。我仍然想知道它们在幕后是如何工作的

实例_exec
是用C编写的,C-api允许您指定在执行方法时self的值

在它成为ruby之前,人们通过在singleton类上定义一个方法并调用该方法来实现它,而不仅仅是在singleton类的上下文中执行东西(您可以在activesupport 2.x或rspec_core的
instance_eval_with_args
中看到这一点)


对象的singleton类本身就是一个对象,因此它有自己的一组实例变量,这些变量不与相应的对象共享,而instance_exec是用C编写的,C-api允许您在执行方法时指定self的值

在它成为ruby之前,人们通过在singleton类上定义一个方法并调用该方法来实现它,而不仅仅是在singleton类的上下文中执行东西(您可以在activesupport 2.x或rspec_core的
instance_eval_with_args
中看到这一点)

对象的singleton类本身就是一个对象,因此它有自己的一组实例变量,这些变量不与相应的对象共享