我正在使用 Ruby 模块。
这工作得很好:
module Mod1
def hello
"Hello from mod 1"
end
end
module Mod2
def hello
"Hello from mod 2"
end
end
class Foo
include Mod1
include Mod2
end
f = Foo.new
puts f.hello
# output: "Hello from mod 2"
这不起作用:
module Mod1
def hello
"Hello from mod 1"
end
end
module Mod2
def hello
"Hello from mod 2"
end
end
class Foo < BasicObject
include Mod1
include Mod2
end
f = Foo.new
puts f.hello
# output: in `<class:Foo>': uninitialized constant Foo::Mod1 (NameError)
这有效:
module Mod1
def hello
"Hello from mod 1"
end
end
module Mod2
def hello
"Hello from mod 2"
end
end
class Foo < BasicObject
include ::Mod1
include ::Mod2
end
f = Foo.new
puts f.hello
您能解释一下原因吗?
最佳答案
在 Ruby 的对象模型中,Object
是在 BasicObject
下定义的。因此,默认情况下,您将在 Object 中定义的任何内容都无法从 BasicObject
访问。
Object.superclass # => BasicObject
现在,您的类 Foo
是 BasicObject
的子类,因此它位于 Object
类的顶部。因此,这些模块对于 Foo 类来说是不可见的。因为模块 Mod1
和 Mod2
是在 Object
类中定义的。您将在顶层定义的任何内容都将进入 Object
类的范围,这就是 Ruby 顶层的定义方式。
您的代码的最后一部分正在工作,因为您明确地将常量路径指定为 include::Mod1
和 include::Mod2
。 ::Mod2
表示您说该模块是在 Object
类中定义的,请在类中为我带来它。
但是代码第二部分的情况并非如此,因此 Foo
无法找到模块,因为您没有给它路径,就像上面的部分一样。
第一部分正在工作,因为模块是在 Object
范围中定义的,并且类 Foo
是 Object
的子类,因此只有 include Mod1
和 `include Mod2
确实按预期工作。
以下是类似的用例,可能会让您对此有所了解:
这里没有错误
class B
module F;end
end
class A < B
include F
end
这里出错
class B
include F
end
class A < B
module F;end
end
# ~> -:2:in `<class:B>': uninitialized constant B::F (NameError)
# ~> from -:1:in `<main>'
关于ruby - Ruby 中的命名空间困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20226754/