根据文档 mod.const_get(sym)
“返回 mod 中命名常量的值。”
我也知道 const_get
默认情况下可能会查找接收者的继承链。所以以下工作:
class A; HELLO = :hello; end
class B < A; end
B.const_get(:HELLO) #=> :hello
我也知道 Ruby 中的类是 Object
的子类,因此您可以使用 const_get
来查找“全局”常量,即使接收方是一个普通类:
class C; end
C.const_get(:Array) #=> Array
然而,这就是我感到困惑的地方——模块不继承 Object
。那么,为什么我仍然可以使用 const_get
从模块中查找“全局”常量?为什么以下方法有效?
module M; end
M.const_get(:Array) #=> Array
如果文档是正确的 - const_get
只是查找在接收器或其父类(super class)下定义的常量。但是在上面的代码中,Object
不是 M
的父类(super class),那么为什么可以查找 Array
呢?
谢谢
最佳答案
你的困惑是正确的......文档没有说明 Ruby 在 Modules
中为查找常量做了一个特例并且已经被修改了 to state this explicitly .如果在正常层次结构中未找到该常量,Ruby 会从 Object
重新开始查找,可以是 found in the source。 .
常量查找本身可能有点令人困惑。举个例子:
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
不过,在这两个地方,访问 Object
级别的常量(如 Array
)都很好(谢天谢地!)。发生的事情是 Ruby 维护了一个“打开的模块定义”列表。如果一个常量有一个明确的范围,比如说 LookHereOnly::Foo
,那么只有 LookHereOnly
和它包含的模块将被搜索。如果未指定作用域(如上例中的 Foo
),Ruby 将查看打开的模块定义以查找常量 Foo
:M::N
,然后是 M
,最后是 Object
。最顶层打开的模块定义始终是 Object
。
所以当打开的类只有M::N
和Object
,就像我示例的最后一部分。
我希望我做对了,因为我自己仍然对不断的查找感到困惑 :-)
关于ruby - Ruby 中 const_get 的混淆行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3165449/