Ruby的def和instance_eval与class_eval

时间:2010-12-10 12:57:40

标签: ruby metaprogramming

我正在阅读 Programming Ruby 1.9 的元编程部分,我无法理解class_eval / {{1}之间内部的内容 }与class_exec / instance_eval

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

self

如果我们使用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_evalclass_eval块内的上下文与完全对我来说是相同的 - 特别是instance_eval指向同一个对象,并且self是一样的。那么正在使local_variables行为不同的块(内部)内部发生了什么?

我能阅读一些文件吗? instance_evalclass_eval的RDoc无济于事。看一下源代码,instance_eval似乎设置了一个单例类对象而class_eval没有 - 但是这个区别在C代码之外是否可见,在Ruby级别上?

2 个答案:

答案 0 :(得分:33)

我认为你的困惑来自于def并不依赖于当前的自我,你可能会认为它是一个拥有自己规则的“当前阶级”。

按照你的例子:

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和instance_eval都设置了   在块的持续时间内自我。   但是,他们的方式不同   为方法设置环境   定义。 class_eval设置了一些东西   好像你是在一个班级的体内   定义,所以方法定义会   定义实例方法相比之下,   在类上调用instance_eval   就像你在里面工作一样   单身自我。因此,   您定义的任何方法都将成为   类方法。

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

一些相关的阅读:

Ruby: instance_eval and class_eval method definitions

Chapter 4 of this most excelent series

答案 1 :(得分:3)

只是添加到@ krusty.ar的答案:defdefine_method为当前的方法定义上下文添加方法(我相信这就是所谓的,我是不确定),而不是当前的self

只是在模块,类或单例类体内部,这两者恰好相同。

但是,例如,在脚本体(也称为顶级)中,selfmain对象,但当前的方法定义上下文是Object