[英]Using Class vs Module for packaging code in Ruby
Let's say I have a bunch of related functions that have no persistent state, say various operations in a string differencing package. 假设我有一堆没有持久状态的相关函数,比如字符串差异包中的各种操作。 I can either define them in a class or module (using
self
) and they can be accessed the exact same way: 我可以在类或模块中定义它们(使用
self
),它们可以以完全相同的方式访问:
class Diff
def self.diff ...
def self.patch ...
end
or 要么
module Diff
def self.diff ...
def self.patch ...
end
I can then do Diff.patch(...)
. 然后我可以做
Diff.patch(...)
。 Which is 'better' (or 'correct')? 哪个'更好'(或'正确')?
The main reason I need to group them up is namespace issues, common function names are all used elsewhere. 我需要将它们分组的主要原因是命名空间问题,常用的函数名称都在其他地方使用。
Edit: Changed example from matrix to diff. 编辑:将示例从矩阵更改为差异。 Matrix is a terrible example as it does have state and everyone started explaining why it's better to write them as methods rather than answer the actual question.
Matrix是一个可怕的例子,因为它确实有状态,每个人都开始解释为什么把它们作为方法而不是回答实际问题更好。 :(
:(
The main difference between modules and classes is that you can not instantiate a module; 模块和类之间的主要区别在于您无法实例化模块; you can't do
obj = MyModule.new
. 你不能做
obj = MyModule.new
。 The assumption of your question is that you don't want to instantiate anything, so I recommend just using a module. 你的问题的假设是你不想实例化任何东西,所以我建议你只使用一个模块。
Still you should reconsider your approach: rather than using arrays of arrays or whatever you are doing to represent a Matrix, it would be more elegant to make your own class to represent a matrix, or find a good class that someone else has already written . 仍然你应该重新考虑你的方法:不是使用数组或你正在做的任何代表矩阵的数组,而是让你自己的类来表示矩阵,或找到别人已经写过的好类更优雅。
In your two examples, you are not actually defining methods in a Class
or a Module
; 在您的两个示例中,您实际上并未在
Class
或Module
定义方法; you are defining singleton methods on an object which happens to be a Class
or a Module
, but could be just about any object. 你是在一个恰好是
Class
或Module
的对象上定义单例方法,但可能只是关于任何对象。 Here's an example with a String
: 这是一个
String
的例子:
Diff = "Use me to access really cool methods"
def Diff.patch
# ...
end
You can do any of these and that will work, but the best way to group related methods is in a Module
as normal instance methods (ie without self.
): 您可以执行其中的任何操作,但这样可以将相关方法分组的最佳方法是在
Module
作为普通实例方法(即没有self.
):
module Diff
extend self # This makes the instance methods available to the Diff module itself
def diff ... # no self.
def patch ...
end
Now you can: 现在你可以:
include Diff
) or from any object (with extend Diff
) include Diff
)或任何对象(使用extend Diff
)中使用此功能 extend self
line which makes it possible to call Diff.patch
. extend self
line,它可以调用Diff.patch
。 For example, in irb
: 例如,在
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
Note : the extend self
will "modify" the Diff
module object itself but it won't have any effect on inclusions of the module. 注意 :
extend self
将“修改” Diff
模块对象本身,但它不会对模块的包含产生任何影响。 Same thing happens for a def self.foo
, the foo
won't be available to any class including it. 对于
def self.foo
也会发生同样的事情, foo
将无法用于包括它的任何类。 In short, only instance methods of Diff
are imported with an include
(or an extend
), not the singleton methods. 简而言之,只有
Diff
实例方法是使用include
(或extend
)导入的,而不是单例方法。 Only subclassing a class will provide inheritance of both instance and singleton methods. 仅对类进行子类化将提供实例和单例方法的继承。
When you actually want the inclusion of a module to provide both instance methods and singleton methods, it's not completely easy. 当你真的希望包含一个模块来提供实例方法和单例方法时,它并不容易。 You have to use the
self.included
hook: 你必须使用
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 Modules are used to specify behaviour, pieces of related functionality. Ruby模块用于指定行为,相关功能。
Ruby Classes are used to specify both state and behaviour, a singular entity. Ruby Classes用于指定状态和行为,一个单一的实体。
There is a maxim in software design that says that code is a liability, so use the less code possible. 软件设计中有一个格言,即代码是一种负担,因此尽可能使用较少的代码。 In the case of Ruby, the difference in code lines is cero.
在Ruby的情况下,代码行的差异是cero。 So you can use either way (if you don't need to save state)
所以你可以使用任何一种方式(如果你不需要保存状态)
If you want to be a purist, then use a Module, since you won't be using the State functionality. 如果您想成为纯粹主义者,请使用模块,因为您不会使用状态功能。 But I wouldn't say that using a class is wrong.
但我不会说使用类是错误的。
As a trivia info: In Ruby a Class is a kind of Module. 作为一个琐事信息:在Ruby中,类是一种模块。
http://www.ruby-doc.org/core-1.9.3/Class.html http://www.ruby-doc.org/core-1.9.3/Class.html
The following also works 以下也有效
Matrix = Object.new
def Matrix.add ...
def Matrix.equals ...
That's because so-called "class methods" are just methods added to a single object, and it doesn't really matter what that object class is. 那是因为所谓的“类方法”只是添加到单个对象的方法,而对象类的含义并不重要。
As a matter of form, the Module is more correct. 作为形式,模块更正确。 You can still create instances of the class, even if it has only class methods.
您仍然可以创建类的实例,即使它只有类方法。 You can think of a module here as a static class of C# or Java.
您可以将此处的模块视为C#或Java的静态类。 Classes also always have the instance related methods (
new
, allocate
, etc.). 类也始终具有与实例相关的方法(
new
, allocate
等)。 Use the Module. 使用模块。 Class methods usually have something to do with objects (creating them, manipulating them).
类方法通常与对象有关(创建它们,操纵它们)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.