我正在玩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
你能解释一下原因吗?
答案 0 :(得分:4)
在Ruby的对象模型中,Object
定义在BasicObject
下面。因此,默认情况下,BasicObject
无法访问您在Object中定义的任何内容。
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>'