Ruby 的 def 和 instance_eval 与 class_eval

标签 ruby metaprogramming

我正在阅读 Programming Ruby 1.9 的元编程部分,但我无法理解 class_eval 之间内部发生了什么|/class_execinstance_eval/instance_exec .

首先,我的理解是defself 的方法表中添加一个方法(类对象):

class A
  puts self  # => A
  def foo; 42; end  # added to the method table of self, so becomes an instance method
end
A.new.foo  # => 42

如果我们使用 class_eval ,我们得到相同的行为:

A.class_eval do
  puts self  # => A
  def bar; 42; end  # same as above
end
A.new.bar  # => 42

但不知何故在 instance_eval情况不同:

A.instance_eval do
  puts self  # => A
  def baz; 42; end  # added to the method table of an anonymous
                    # singleton class of self, so becomes a class method
end
puts A.baz  # => 42

s = 'string'
s.instance_eval do ... end  # same behavior, so now def creates an instance method

所以我明白了 class_eval 之间的功能区别和 instance_eval .

但是class_eval里面的上下文和 instance_eval block 在我看来完全一样——特别是,self指向同一个对象,local_variables是相同的。那么在生成 def 的 block 内部(内部)发生了什么?表现不同?

有没有我可以阅读的文档? instance_eval 的 RDoc和 class_eval没有帮助。查看源代码,instance_eval似乎设置了一个单例类对象,而 class_eval没有——但是这种差异在 C 代码之外,在 Ruby 级别上是否可见?

最佳答案

我认为您的困惑来自 def 不依赖于当前 self 这一事实,您可能将其视为具有自己规则的“当前类”。

按照你的例子:

class A
  # defs here go to A
  puts self  # => A
  class << self
     #defs here go to A's eigenclass
  end
end

A.class_eval do
  #defs here go to A
end

A.instance_eval do
  #defs here go to A's eigenclass     
end

s = "Hello World"

class << s
  #defs here go to s's eigenclass
end

这是本章中讨论该问题的部分,并且非常清楚该行为

class_eval and instance_eval both set self for the duration of the block. However, they differ in the way they set up the environment for method definition. class_eval sets things up as if you were in the body of a class definition, so method definitions will define instance methods In contrast, calling instance_eval on a class acts as if you were working inside the singleton class of self. Therefore, any methods you define will become class methods.

我认为唯一值得补充的是您可以在任何对象中调用 instance_eval,而不仅仅是类,并且行为不会改变但会产生不同的结果。

一些相关阅读:

Ruby: instance_eval and class_eval method definitions

Chapter 4 of this most excelent series

关于Ruby 的 def 和 instance_eval 与 class_eval,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4409023/

相关文章:

ruby-on-rails - 报错 - 在 Snow Leopard 上安装 RVM

ruby-on-rails - 第 8 章 ruby​​tutorial - NoMethodError : undefined method `forget' for nil:NilClass

ruby-on-rails - 如何让 Haml 与 Rails 一起工作?

ruby - 是否有类似于 Class#inherited 的钩子(Hook),仅在 Ruby 类定义后触发?

c++ - 从迭代器中获取 const_iterator

ruby - 如何以编程方式确定哪个类/模块定义了被调用的方法?

ruby-on-rails - 如何坚持 REST?

ruby - 我如何使用 trollop 进行位置论证?

metaprogramming - 类型化元编程语言

r - 在 R 文件中查找顶级函数