Ruby在持续可访问性方面似乎已经多次发生过变化.对Ruby 1.9.2,有关于这个问题不断的无障碍说明和回答在这里,但写的是什么也不再成立了.
在Ruby 2.3中,如果我在类中定义了一个常量:
class A
Foo = :a
end
Run Code Online (Sandbox Code Playgroud)
我无法通过instance_eval或访问它class_eval:
A.new.instance_eval{Foo} # => error
A.class_eval{Foo} # => error
A.instance_eval{Foo} # => error
Run Code Online (Sandbox Code Playgroud)
虽然我可以从课堂上访问它:
class A; Foo end # => :a
Run Code Online (Sandbox Code Playgroud)
从Ruby 2.3开始,常量可访问性如何工作?如果可能的话,请解释Ruby中常量可访问性的历史变化以及导致它们的参数.
Ruby 中的常量查找使用词法作用域来遍历当前作用域并包含模块。查找路径可以通过查看Module.nesting
> module Out
> module In
> puts Module.nesting
> end
> end
Out::In # gets searched for a given constant first
Out
Run Code Online (Sandbox Code Playgroud)
块内的查找保持不变以启用闭包行为,即使对于class_eval.
instance_eval然而,在 Ruby 1.9 中, 、instance_exec、
class_eval、 和 的接收器class_exec被预先添加到查找路径中,这意味着所有常量引用将首先在接收器的作用域中查找。
Yehuda Katz 提出了一个问题,指出存在严重损坏:
考虑 RSpec 的情况:
Run Code Online (Sandbox Code Playgroud)describe "Date" do it "equals itself" do Date.today.should == Date.today end end如果我们先使用动态作用域,那么如果 RSpec 添加 Spec::Date,它会突然破坏这个规范。词法范围更加直观,并且是当今许多正常用途所期望的。
该行为随后恢复到 1.8。