Ruby 中 const_get 的行为令人困惑?

2024-04-24

根据文档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只需查找接收者或其超类下定义的常量即可。但在上面的代码中,Object不是一个超类M,那么为什么可以查找Array ?

Thanks


你感到困惑是正确的......该文档没有说明 Ruby 为查找常量提供了特殊情况Modules并已修改明确说明这一点 http://ruby-doc.org/core-1.9.3/Module.html#const_get-method。如果在正常层次结构中没有找到该常量,Ruby 会从以下位置重新开始查找:Object,可以是在源码中找到 http://github.com/ruby/ruby/blob/v1_9_2_preview3/variable.c#L1594.

持续查找本身可能会有点令人困惑。举个例子:

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, then only LookHereOnly及其包含的模块将被搜索。如果没有指定范围(例如Foo在上面的示例中),Ruby 将查找打开的模块定义以查找常量Foo: M::N, then M最后Object。最顶层打开的模块定义始终是Object.

So M::N.const_get :Foo相当于访问Foo当开设的课程只有M::N and Object,就像我示例的最后一部分一样。

我希望我做对了,因为我自己仍然对不断的查找感到困惑:-)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Ruby 中 const_get 的行为令人困惑? 的相关文章

随机推荐