所以Module
可以在Ruby中用来提供除了mixins之外的命名空间,如下所示:
module SomeNamespace
class Animal
end
end
animal = SomeNamespace::Animal.new
但是我也见过下面的用法:
module SomeNamespace
end
class SomeNamespace::Animal
end
animal = SomeNamespace::Animal.new
我的问题是它们有什么不同(如果有的话),哪个更符合Ruby的习惯?
区别在于嵌套。
在下面的例子中,你可以看到前一种方法使用类Foo,可以获得外部作用域的常量变量BAR_A而没有错误。
同时,类Baz将爆炸,错误为未初始化的常量A::B::Baz::BAR_A。因为它没有隐式地引入A::*,只有显式地引入A::B::*。
module A
BAR_A = 'Bar A!'
module B
BAR_B = 'Bar B!'
class Foo
p BAR_A
p BAR_B
end
end
end
class A::B::Baz
p BAR_A
p BAR_B
end
这两种行为都有它们的地方。在我看来,社区中对于哪一条才是真正的Ruby之路(tm)并没有真正的共识。我个人大多数时候使用前者。
这两种方法之间的唯一区别是,如果之前没有声明名称空间,第二种方法将抛出uninitialized constant Object::SomeNamespace
。
当在单个文件中声明时,我会选择第一个,因为您不必重复SomeNamespace
。
当使用多个文件时,我也使用第二个文件,以避免遇到以下问题:
# in a.rb
require 'b'
module SomeNamespace
def self.animal
Animal.new
end
end
# in b.rb
class SomeNamespace::Animal
end
# irb
require 'a' # explodes with the uninitialized constant error
这个例子可能是人为的,但是如果您的代码库稍微大一点,很容易触发它。我通常使用显式的方式(你的第一个)来避免这种情况。
在使用第二种形式时,有一点可能会有所帮助,那就是它会检测名称空间中的拼写错误。
似乎没有一种既定的方法来创建名称空间,例如,设计混合了两种方法:第一种,第二种。