gpt4 book ai didi

ruby - Ruby 的 Object#const_get 是如何工作的?

转载 作者:数据小太阳 更新时间:2023-10-29 06:43:40 26 4
gpt4 key购买 nike

我最近发现 Ruby (2.2.1) 有一些“有趣”的行为。

module Foo
class Foo
end
class Bar
end
end

Foo.const_get('Foo') #=> Foo::Foo
Foo.const_get('Bar') #=> Foo::Bar
Foo.const_get('Foo::Foo') #=> Foo
Foo.const_get('Foo::Bar') #=> NameError: uninitialized constant Foo::Foo::Bar
Foo.const_get('Foo::Foo::Bar') #=> Foo::Bar
Foo.const_get('Foo::Foo::Foo::Bar') #=> NameError: uninitialized constant Foo::Foo::Bar
Foo.const_get('Foo::Foo::Foo::Foo::Bar') #=> Foo::Bar
Foo.const_get('Foo::Foo::Foo') #=> Foo::Foo
Foo.const_get('Foo::Foo::Foo::Foo') #=> Foo
Foo.const_get('Foo::Foo::Foo::Foo::Foo') #=> Foo::Foo
Foo.const_get('Foo::Foo::Foo::Foo::Foo::Foo') #=> Foo

这有点令人惊讶。我的理解是,const_get 首先在接收方的常量集合中查找常量,然后查看 Object 的常量。好的。为什么上面的第四个 Foo#const_get 失败而第三个没有呢?

我也很好奇为什么调用 Foo#const_get 会根据您添加的 ::Foo 数量在模块和类之间交替调用。

最佳答案

The docs say :

This method will recursively look up constant names if a namespaced class name is provided.

因此 Foo.const_get('Foo::Bar')Foo.const_get('Foo').const_get('Bar') 基本相同。使用这种解释,您的结果是有意义的。

你的第三个例子:

Foo.const_get('Foo::Foo')

相同
Foo.const_get('Foo').const_get('Foo')

第一个 const_get 查看在顶层 Foo(模块)中定义的常量,并找到嵌套类。所以整个事情实际上变成了:

Foo::Foo.const_get('Foo')

然后第二个调用查看类,首先查看任何包含的常量(没有找到),然后查看它的祖先。 Object 是一个祖先,并且具有作为常量的顶级 Foo 模块,因此可以找到并返回它。

这也解释了添加额外的 ::Foo 时的交替。交替发生在查找嵌套类的顶级模块的 const_get 和查找继承链并查找顶级模块的嵌套类之间。

第四个例子,Foo.const_get('Foo::Bar'),抛出一个异常,也可以解释。相当于

Foo.const_get('Foo').const_get('Bar')

第一部分,Foo.const_get('Foo') 与上面的情况相同,评估为 Foo::Foo,所以整个事情现在有效变成:

Foo::Foo.const_get('Bar')

现在嵌套的 Foo 类不包含 Bar 常量,查找继承链,Object 也不包含,所以结果是 NameError

关于ruby - Ruby 的 Object#const_get 是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38086328/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com