我用一个常数&方法:
class A
FOO = 'hello'
def bar
puts FOO
end
end
A.new.bar
=> 'hello'
一切都按预期工作。但是,当我这样做时:
A.class_eval do
def bar
puts FOO
end
end
A.new.bar
NameError: uninitialized constant FOO
奇怪......为了解决这个问题,我正在做:
A.class_eval do
def bar
puts self.class::FOO
end
end
为什么会出现这种情况有什么好的解释?
答案 0 :(得分:5)
查找常量
所以,让我们做Ruby做的事情:
class Object
- 但Object
没有名为FOO
的常量,并且它的祖先Kernel
和BasicObject
。 Ergo:Ruby是对的。常量查找路径中没有名为FOO
的常量。它没有从范围中删除FOO
,它从来没有开始。
[Ruby的反射API实际上可以让您访问所需的任何内容:#1与Module.nesting
完全相同,而#2(几乎)与Module.nesting.first.ancestors
相同。]
您可能会想:等待,不是module_eval
模块声明吗?不,不是!它就像任何其他方法一样,采用与任何其他块一样的块。它不会以任何方式改变常量查找规则。
请注意,这并不完全正确:毕竟,例如,例如,instance_eval
会更改方法查找规则,因此module_eval
更改常量查找规则是不可想象的。更令人困惑的是,当用String
而不是块调用时,它实际上 更改了Module.nesting
,从而改变了常量查找规则!< / p>