[英]Using Class vs Module for packaging code in Ruby
假设我有一堆没有持久状态的相关函数,比如字符串差异包中的各种操作。 我可以在类或模块中定义它们(使用self
),它们可以以完全相同的方式访问:
class Diff
def self.diff ...
def self.patch ...
end
要么
module Diff
def self.diff ...
def self.patch ...
end
然后我可以做Diff.patch(...)
。 哪个'更好'(或'正确')?
我需要将它们分组的主要原因是命名空间问题,常用的函数名称都在其他地方使用。
编辑:将示例从矩阵更改为差异。 Matrix是一个可怕的例子,因为它确实有状态,每个人都开始解释为什么把它们作为方法而不是回答实际问题更好。 :(
模块和类之间的主要区别在于您无法实例化模块; 你不能做obj = MyModule.new
。 你的问题的假设是你不想实例化任何东西,所以我建议你只使用一个模块。
仍然你应该重新考虑你的方法:不是使用数组或你正在做的任何代表矩阵的数组,而是让你自己的类来表示矩阵,或找到别人已经写过的好类更优雅。
在您的两个示例中,您实际上并未在Class
或Module
定义方法; 你是在一个恰好是Class
或Module
的对象上定义单例方法,但可能只是关于任何对象。 这是一个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
)中使用此功能 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
)导入的,而不是单例方法。 仅对类进行子类化将提供实例和单例方法的继承。
当你真的希望包含一个模块来提供实例方法和单例方法时,它并不容易。 你必须使用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
Ruby模块用于指定行为,相关功能。
Ruby Classes用于指定状态和行为,一个单一的实体。
软件设计中有一个格言,即代码是一种负担,因此尽可能使用较少的代码。 在Ruby的情况下,代码行的差异是cero。 所以你可以使用任何一种方式(如果你不需要保存状态)
如果您想成为纯粹主义者,请使用模块,因为您不会使用状态功能。 但我不会说使用类是错误的。
作为一个琐事信息:在Ruby中,类是一种模块。
以下也有效
Matrix = Object.new
def Matrix.add ...
def Matrix.equals ...
那是因为所谓的“类方法”只是添加到单个对象的方法,而对象类的含义并不重要。
作为形式,模块更正确。 您仍然可以创建类的实例,即使它只有类方法。 您可以将此处的模块视为C#或Java的静态类。 类也始终具有与实例相关的方法( new
, allocate
等)。 使用模块。 类方法通常与对象有关(创建它们,操纵它们)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.