在class_eval中访问类变量失败

时间:2013-08-17 22:50:42

标签: ruby

任何人都可以解释以下行为:

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 { ... }

1 个答案:

答案 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