Ruby 中 const_get 的混淆行为? [英] Confusing behaviour of const_get in Ruby?

查看:29
本文介绍了Ruby 中 const_get 的混淆行为?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据文档 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::NObject,就像我例子的最后一部分一样.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆