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

Mar*_*tin 38 ruby

因此Module可以在Ruby中使用除了mixins之外还提供命名空间,如下所示:

module SomeNamespace
  class Animal

  end
end

animal = SomeNamespace::Animal.new
Run Code Online (Sandbox Code Playgroud)

但我也看到过以下用途:

module SomeNamespace
end

class SomeNamespace::Animal

end

animal = SomeNamespace::Animal.new
Run Code Online (Sandbox Code Playgroud)

我的问题是它们是如何不同的(如果它们是),哪个是更惯用的Ruby?

pea*_*kxu 42

不同之处在于嵌套.

在下面的示例中,您可以看到使用类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
Run Code Online (Sandbox Code Playgroud)

两种行为都有自己的位置.在我看来,社区中没有真正的共识,哪一个是真正的Ruby方式(tm).大多数时候我个人使用前者.


Ben*_*ret 6

两种方法之间的唯一区别是,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
Run Code Online (Sandbox Code Playgroud)

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

使用第二种形式时可能有用的一点是它会检测命名空间中的拼写错误.

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