我正在阅读 Programming Ruby 1.9 的元编程部分,我无法理解class_eval
/ {{1}之间内部的内容 }与class_exec
/ instance_eval
。
首先,我的理解是instance_exec
为def
(类对象)的方法表添加了一个方法:
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_eval
和class_eval
块内的上下文与完全对我来说是相同的 - 特别是instance_eval
指向同一个对象,并且self
是一样的。那么正在使local_variables
行为不同的块(内部)内部发生了什么?
我能阅读一些文件吗? instance_eval和class_eval的RDoc无济于事。看一下源代码,instance_eval似乎设置了一个单例类对象而class_eval没有 - 但是这个区别在C代码之外是否可见,在Ruby级别上?
答案 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,而不仅仅是类,并且行为不会改变但会产生不同的后果。
一些相关的阅读:
答案 1 :(得分:3)
只是添加到@ krusty.ar的答案:def
和define_method
为当前的方法定义上下文添加方法(我相信这就是所谓的,我是不确定),而不是当前的self
。
只是在模块,类或单例类体内部,这两者恰好相同。
但是,例如,在脚本体(也称为顶级)中,self
是main
对象,但当前的方法定义上下文是Object
。