2013-11-26 60 views
2

我在玩Ruby模塊。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 

能否請您解釋一下爲什麼?

回答

4

在Ruby的對象模型中,Object定義在BasicObject的下方。所以無論你在Object中定義什麼,默認情況下都不能從BasicObject訪問。

Object.superclass # => BasicObject 

現在你Foo類是BasicObject一個子類,如此這般頂部Object類的。因此這些模塊對Foo類不可見。因爲模塊Mod1Mod2是在Object類中定義的。您將在頂層定義的任何東西都將成爲Object類的範圍,這就是Ruby定義的頂層級別。

您的代碼的最後一部分正在工作,因爲您明確指定了常量路徑爲include ::Mod1include ::Mod2::Mod2意味着你所說的模塊在Object類中定義,在課堂上將它帶給我。

但是對於代碼的第二部分,情況並非如此,所以Foo無法找出模塊,因爲您沒有給出它的路徑,就像上面的部分一樣。

第一部分工作,爲模塊在Object範圍定義,並且類FooObject子類,因此僅include Mod1`include Mod2確實按預期方式工作。

這裏是類似用途的情況下,它可能給你一些光在這:

這裏沒有錯誤這裏

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>' 
+0

class B module F;end end class A < B include F end 

錯誤的模塊是一個類中是明確的。我所缺少的是一個概念,即頂層的所有東西都在'對象'範圍內。謝謝! – Shinigami