我正在阅读 Programming Ruby 1.9 的元编程部分,但我无法理解 class_eval
之间内部发生了什么|/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
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 的 def 和 instance_eval 与 class_eval,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4409023/