使用Class vs Module在Ruby中打包代码

假设我有一堆没有持久状态的相关函数,比如字符串差异包中的各种操作。 我可以在类或模块中定义它们(使用self ),它们可以以完全相同的方式访问:

 class Diff def self.diff ... def self.patch ... end 

要么

 module Diff def self.diff ... def self.patch ... end 

然后我可以做Diff.patch(...) 。 哪个’更好’(或’正确’)?

我需要将它们分组的主要原因是名称空间问题,常用函数名称都在其他地方使用。

编辑:将示例从矩阵更改为差异。 矩阵是一个可怕的例子,因为它确实有状态,每个人都开始解释为什么把它们写成方法而不是回答实际问题更好。 🙁

在您的两个示例中,您实际上并未在ClassModule定义方法; 你是在一个恰好是ClassModule的对象上定义单例方法,但可能只是关于任何对象。 这是一个String的例子:

 Diff = "Use me to access really cool methods" def Diff.patch # ... end 

您可以执行其中的任何操作,但这样可以将相关方法分组的最佳方法是在Module作为普通实例方法(即没有self. ):

 module Diff extend self # This makes the instance methods available to the Diff module itself def diff ... # no self. def patch ... end 

现在你可以:

  • 在任何类( include Diff )或任何对象(使用extend Diff )中使用此function
  • 这种用法的一个例子是extend self line,它可以调用Diff.patch
  • 甚至在全局命名空间中使用这些方法

例如,在irb

 class Foo include Diff end Foo.new.patch # => calls the patch method Diff.patch # => also calls Diff.patch include Diff # => now you can call methods directly: patch # => also calls the patch method 

注意extend self将“修改” Diff模块对象本身,但它不会对模块的包含产生任何影响。 对于def self.foo也会发生同样的事情, foo将无法用于包括它的任何类。 简而言之,只有Diff实例方法是使用include (或extend )导入的,而不是单例方法。 只有inheritance类才能提供实例和单例方法的inheritance。

当你真的希望包含一个模块来提供实例方法和单例方法时,这并不容易。 你必须使用self.included钩子:

 module Foo def some_instance_method; end module ClassMethods def some_singleton_method; end end def self.included(base) base.send :extend, ClassMethods end def self.will_not_be_included_in_any_way; end end class Bar include Foo end # Bar has now instance methods: Bar.new.some_instance_method # => nil # and singleton methods: Bar.some_singleton_method # => nil 

模块和类之间的主要区别在于您无法实例化模块; 你不能做obj = MyModule.new 。 你的问题的假设是你不想实例化任何东西,所以我建议你只使用一个模块。

仍然你应该重新考虑你的方法:不是使用数组或你正在做的任何代表矩阵的数组,而是让你自己的类来表示矩阵,或找到别人已经写过的好类更优雅。

Ruby模块用于指定行为,相关function的各个部分。

Ruby Classes用于指定状态和行为,一个单一的实体。

软件设计中有一个格言,即代码是一种负担,因此尽可能使用较少的代码。 在Ruby的情况下,代码行的差异是cero。 所以你可以使用任何一种方式(如果你不需要保存状态)

如果您想成为纯粹主义者,请使用模块,因为您不会使用状态function。 但我不会说使用类是错误的。

作为一个琐事信息:在Ruby中,一个类是一种模块。

http://www.ruby-doc.org/core-1.9.3/Class.html

以下也有效

 Matrix = Object.new def Matrix.add ... def Matrix.equals ... 

那是因为所谓的“类方法”只是添加到单个对象的方法,而对象类的含义并不重要。

作为forms,模块更正确。 您仍然可以创建该类的实例,即使它只有类方法。 您可以将此处的模块视为C#或Java的静态类。 类也始终具有与实例相关的方法( newallocate等)。 使用模块。 类方法通常与对象有关(创建它们,操纵它们)。