这些 Ruby 命名空间约定之间有什么区别?



所以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

这个例子可能是人为的,但是如果您的代码库稍微大一点,很容易触发它。我通常使用显式的方式(你的第一个)来避免这种情况。

在使用第二种形式时,有一点可能会有所帮助,那就是它会检测名称空间中的拼写错误。

似乎没有一种既定的方法来创建名称空间,例如,设计混合了两种方法:第一种,第二种。

最新更新