任何人都可以解释以下行为:
class X
@@x = 1
end
X.class_eval { @@x } #=> NameError: uninitialized class variable ...
X.class_eval { class_variable_get :@@x } #=> 1
在MRI 1.8.7,1.9.2,1.9.3和2.0.0中测试,结果相同。为什么我不能直接在@@x
块内部使用X.class_eval { ... }
?
答案 0 :(得分:1)
这种情况发生类变量访问是词法范围的。当你运行代码提示时,Ruby实际上会给你一个警告:
警告:来自toplevel的类变量访问
表示正在顶级作用域中解析类变量。我们可以通过在class_eval
内部分配然后在外部访问它来证明这是真的:
X.class_eval { @@x = 42 }
@@x #=> 42
这证明了类变量的词汇性质,导致class_eval
(变异self
)无效。†
不幸的是,我无法找到记录此行为的好参考,但Programming Ruby’s section “Scope of Constants and Variables”中涵盖了有关类变量赋值的其他一些细节。
†请注意,X.class_variable_get(:@@x)
也是42
,因为X
的{{1}}是从顶层继承的。我们可以通过创建一个没有明确@@x
的新类来看到这一点:@@x
。