Ruby 中 const_get 的混淆行为? [英] Confusing behaviour of const_get in Ruby?
问题描述
根据文档 mod.const_get(sym)
返回 mod 中命名常量的值."
According to the documentation mod.const_get(sym)
"Returns the value of the named constant in mod."
我也知道 const_get
默认可以查找接收者的继承链.所以以下工作:
I also know that const_get
by default may look up the inheritance chain of the receiver. So the following works:
class A; HELLO = :hello; end
class B < A; end
B.const_get(:HELLO) #=> :hello
我也知道 Ruby 子类 Object
中的类,因此即使接收器是普通类,您也可以使用 const_get
查找全局"常量:
I also know that classes in Ruby subclass Object
, so that you can use const_get
to look up 'global' constants even though the receiver is a normal class:
class C; end
C.const_get(:Array) #=> Array
然而,这就是我感到困惑的地方——模块不能子类化 Object
.那么为什么我仍然可以使用 const_get
从模块中查找全局"常量?为什么以下工作?
However, and this is where i'm confused -- modules do not subclass Object
. So why can I still look up 'global' constants from a module using const_get
? Why does the following work?
module M; end
M.const_get(:Array) #=> Array
如果文档是正确的 - const_get
只需查找在接收器或其超类下定义的常量.但是在上面的代码中,Object
不是M
的超类,那么为什么可以查找Array
?
If the documentation is correct - const_get
simply looks up the constant defined under the receiver or its superclasses. But in the code immediately above, Object
is not a superclass of M
, so why is it possible to look up Array
?
谢谢
推荐答案
您的困惑是正确的... 该文档没有说明 Ruby 为在 Modules
并已修改明确说明这一点.如果在正常层次结构中没有找到常量,Ruby 会从 Object
重新开始查找,例如 在源代码中找到.
You are correct to be confused... The doc didn't state that Ruby makes a special case for lookup of constants in Modules
and has been modified to state this explicitly. If the constant has not been found in the normal hierarchy, Ruby restarts the lookup from Object
, as can be found in the source.
持续查找本身可能有点混乱.以下面的例子:
Constant lookup by itself can be bit confusing. Take the following example:
module M
Foo = :bar
module N
# Accessing Foo here is fine:
p Foo # => bar
end
end
module M::N
# Accessing Foo here isn't
p Foo # => uninitialized constant M::N::Foo
end
p M::N.const_get :Foo # => uninitialized constant M::N::Foo
不过,在这两个地方,访问像 Array
这样的 Object
级别的常量都很好(感谢上帝!).发生的事情是 Ruby 维护了一个打开的模块定义"列表.如果常量具有明确的作用域,例如 LookHereOnly::Foo
,则将搜索 only LookHereOnly
及其包含的模块.如果没有指定作用域(如上例中的 Foo
),Ruby 将查看打开的模块定义以找到常量 Foo
:M::N
,然后是 M
,最后是 Object
.最上面打开的模块定义总是Object
.
In both places, though, accessing Object
level constants like Array
is fine (thank god!). What's going on is that Ruby maintains a list of "opened Module definitions". If a constant has an explicit scope, say LookHereOnly::Foo
, then only LookHereOnly
and its included modules will be searched. If no scope is specified (like Foo
in the example above), Ruby will look through the opened module definitions to find the constant Foo
: M::N
, then M
and finally Object
. The topmost opened module definition is always Object
.
所以 M::N.const_get :Foo
等价于访问 Foo
当打开的类只有 M::N
和 Object
,就像我例子的最后一部分一样.
So M::N.const_get :Foo
is equivalent to accessing Foo
when the opened classes are only M::N
and Object
, like in the last part of my example.
我希望我做对了,因为我自己仍然对不断的查找感到困惑:-)
I hope I got this right, coz I'm still confused by constant lookups myself :-)
这篇关于Ruby 中 const_get 的混淆行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!