ruby - Ruby 中 const_get 的混淆行为?

标签 ruby

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

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

关于ruby - Ruby 中 const_get 的混淆行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3165449/

相关文章:

ruby + Nokogiri : How to create XML node with attribute=value?

ruby - 如何在 Rspec 测试中允许对模块常量的非限定访问?

ruby-on-rails - 如何随机生成文件链接?

ruby - 这些 Array Initializations 中的哪个在 Ruby 中更好?

regex - 在 Ruby 中仅删除字符串中的非前导和非尾随空格?

ruby - 按哈希属性的值按降序对哈希数组进行排序,保留哈希的初始顺序

ruby - 使用中间人将日期从 yaml 打印到 ruby

ruby - 嵌套 if else inside .each 迭代

ruby-on-rails - 在 Ruby 上访问 Google 通讯录 API

ruby - 在 Ruby 中使用命名正则表达式组