Ruby在持续可访问性方面似乎已经多次发生过变化。对于Ruby 1.9.2,在问题和答案here中有关于持续可访问性的描述,但是那里写的不再是真实的。
在Ruby 2.3中,如果我在类中定义了一个常量:
class A
Foo = :a
end
我无法通过instance_eval
或class_eval
A.new.instance_eval{Foo} # => error
A.class_eval{Foo} # => error
A.instance_eval{Foo} # => error
虽然我可以从课堂上访问它:
class A; Foo end # => :a
Ruby 2.3中的常量可访问性如何工作?如果可能的话,请解释Ruby中常量可访问性的历史变化以及导致它们的参数。
答案 0 :(得分:2)
注意:以下答案基于Ruby 2.2,尚未在2.3上验证
的文档在mod的上下文中计算字符串或块,除外 给出一个块,常量/类变量查找不受影响。
虽然下面的代码出错了,
A.class_eval{Foo} # uninitialized constant Foo (NameError)
以下作品正在eval
编辑。
A.class_eval("Foo") #=> :a
似乎Constant需要模块名称或类名才能正确评估它。以下是:
A.class_eval{self::Foo} #=> :a
那么,这些:
A.new.instance_eval {self.class::Foo} #=> :a
A.instance_eval {self::Foo} #=> :a
答案 1 :(得分:2)
Ruby中的常量查找使用lexical scope遍历当前作用域并包含模块。可以通过Module.nesting
> module Out
> module In
> puts Module.nesting
> end
> end
Out::In # gets searched for a given constant first
Out
查询在块内保持相同以启用关闭行为,即使对于class_eval
也是如此。
然而,在Ruby 1.9中,instance_eval
,instance_exec
的接收者,
class_eval
和class_exec
被添加到查找路径之前,这意味着所有常量引用都将首先在接收器的范围中查找。
Yehuda Katz提出issue引用严重破坏:
考虑RSpec的情况:
describe "Date" do it "equals itself" do Date.today.should == Date.today end end
如果我们首先使用动态范围,那么如果RSpec添加Spec :: Date,它将会 突然打破这个规格。词汇范围更直观,而且是 今天许多正常用途的预期。
随后行为reverted又恢复到1.8。