如何确定持续可访问性?

saw*_*awa 7 ruby constants

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中常量可访问性的历史变化以及导致它们的参数.

fyl*_*ooi 3

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_execclass_eval、 和 的接收器class_exec被预先添加到查找路径中,这意味着所有常量引用将首先在接收器的作用域中查找。

Yehuda Katz 提出了一个问题,指出存在严重损坏:

考虑 RSpec 的情况:

describe "Date" do   
  it "equals itself" do
    Date.today.should == Date.today   
  end 
end
Run Code Online (Sandbox Code Playgroud)

如果我们先使用动态作用域,那么如果 RSpec 添加 Spec::Date,它会突然破坏这个规范。词法范围更加直观,并且是当今许多正常用途所期望的。

该行为随后恢复到 1.8。