是否可以给一个子模块与顶级类相同的名称? [英] Is it possible to give a sub-module the same name as a top-level class?
问题描述
背景:
这里有一个问题,简化为一个最小的例子:
#bar.rb
class Bar
end
#foo / bar.rb
模块Foo :: Bar
end
#foo.rb
class Foo
include Foo :: Bar
end
.rb
要求'bar'
要求'foo'
➔ruby runner.rb
./foo.rb:2:warning:toplevel常量由Foo :: Bar引用的bar
./foo.rb:2:in`include':wrong参数类型Class(expected module)(TypeError)
from ./foo.rb:2
from runner.rb:2:in`require'
from runner.rb:2
你的代码示例非常清楚。
当你运行Ruby代码 即使您可以说服 重命名 那么可以做什么呢?在高水平,你必须打破周期不知何故。最简单的是在两个部分中定义 希望这有助。 Background: Here's the problem, distilled down to a minimal example:
Excellent; your code sample is very clarifying. What you have there is a garden-variety circular dependency, obscured by the peculiarities of Ruby's scope-resolution operator. When you run the Ruby code Even if you could persuade Renaming So what can you do? At a high level, you have to break the cycle somehow. Simplest is to define Hope this helps. 这篇关于是否可以给一个子模块与顶级类相同的名称?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!当你运行Ruby代码时, require'foo'
,ruby发现 foo.rb
并执行它,然后找到 foo / bar.rb
并执行。所以当Ruby遇到你的
Foo
类并执行 include Foo :: Bar
时,它会寻找一个名为 Bar
在类 Foo
中,因为这是 Foo :: Bar
。当它找不到一个时,它会在其他包围范围中搜索名为 Bar
的常量,并最终在顶级找到它。但是 Bar
是一个类,因此不能 include
d。 / p>
require
运行 foo / bar.rb
之前 foo.rb
,它不会帮助; 模块Foo :: Bar
表示找到常量 Foo
,如果它是一个类或模块,模块中调用 Bar
。 Foo
尚未创建,因此require仍会失败。
Foo :: Bar
到 Foo :: UserBar
也不会有帮助,因为名称clash不会最终出错。
Foo
:
bar.rb
class Bar
A = 4
end
#foo.rb
class Foo
#不依赖的东西在Foo :: Bar去这里。
end
#foo / bar.rb
模块Foo :: Bar
A = 5
end
类Foo #是的,我们重新打开foo里面的类Foo / bar.rb
include Bar#注意,你不需要Foo ::因为我们首先自动搜索Foo。
end
Bar :: A#=> 4
Foo :: Bar :: A#=> 5
# bar.rb
class Bar
end
# foo/bar.rb
module Foo::Bar
end
# foo.rb
class Foo
include Foo::Bar
end
# runner.rb
require 'bar'
require 'foo'
➔ ruby runner.rb
./foo.rb:2: warning: toplevel constant Bar referenced by Foo::Bar
./foo.rb:2:in `include': wrong argument type Class (expected Module) (TypeError)
from ./foo.rb:2
from runner.rb:2:in `require'
from runner.rb:2
require 'foo'
, ruby finds foo.rb
and executes it, and then finds foo/bar.rb
and executes that. So when Ruby encounters your Foo
class and executes include Foo::Bar
, it looks for a constant named Bar
in the class Foo
, because that's what Foo::Bar
denotes. When it fails to find one, it searches other enclosing scopes for constants named Bar
, and eventually finds it at the top level. But that Bar
is a class, and so can't be include
d.require
to run foo/bar.rb
before foo.rb
, it wouldn't help; module Foo::Bar
means "find the constant Foo
, and if it's a class or a module, start defining a module within it called Bar
". Foo
won't have been created yet, so the require will still fail.Foo::Bar
to Foo::UserBar
won't help either, since the name clash isn't ultimately at fault.Foo
in two parts, like so:# bar.rb
class Bar
A = 4
end
# foo.rb
class Foo
# Stuff that doesn't depend on Foo::Bar goes here.
end
# foo/bar.rb
module Foo::Bar
A = 5
end
class Foo # Yep, we re-open class Foo inside foo/bar.rb
include Bar # Note that you don't need Foo:: as we automatically search Foo first.
end
Bar::A # => 4
Foo::Bar::A # => 5