1

我从文档中找到了以下代码摘录instance_exec

  class KlassWithSecret
    def initialize
      @secret = 99
    end
  end
  k = KlassWithSecret.new
  k.instance_exec(5) {|x| @secret+x }   #=> 104

我对 instance_exec 的理解如下图所示,它在其单例类中添加了 @secret + 5

  +-----------------------+
  |   singleton class do  |
  |     def method1       |
  |     ...               |
  |     end               |
  |     ...               |
  |     @secret + 5       |
  |   end                 |
  |                       |
  |                       |
  +-----------+-----------+
              |
    +---------+-------+
    |  instance k     |
    |   @secret       |
    |                 |
    +-----------------+

所以我想出了使用 class_exec 的代码来获得相同的结果

k.singleton_class.class_exec(5) {|x| @secret + x}

它给了我一个@secret is nil 错误,我想知道为什么会这样以及我的理解有什么问题

更新:

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

4

1 回答 1

1

instance_exec是用 C 编写的,c-api 允许您在执行方法时指定 self 的值。

在它进入 ruby​​ 之前,人们通过在单例类上定义一个方法并调用它来实现它,而不仅仅是在单例类的上下文中执行东西(你可以在 activesupport 2.x 或 rspec_core's 中看到这一点instance_eval_with_args

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

于 2012-07-02T07:28:27.537 回答