使用Class vs Module在Ruby中打包代码 [英] Using Class vs Module for packaging code in Ruby
问题描述
比方说,我有一堆没有持久状态的相关函数,例如字符串差异包中的各种操作.我可以在类或模块中定义它们(使用self
),并且可以使用完全相同的方式对其进行访问:
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:
class Diff
def self.diff ...
def self.patch ...
end
或
module Diff
def self.diff ...
def self.patch ...
end
然后我可以做Diff.patch(...)
.哪个是更好"(或正确")?
I can then do 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.
将示例从矩阵更改为差异. Matrix是一个可怕的示例,因为它确实有状态,并且每个人都开始解释为什么将它们编写为方法而不是回答实际问题更好. :(
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. :(
推荐答案
在您的两个示例中,您实际上并没有在Class
或Module
中定义方法.您正在一个对象上定义单例方法,该对象恰巧是Class
或Module
,但几乎可以是任何对象.这是String
的示例:
In your two examples, you are not actually defining methods in a Class
or a 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. Here's an example with a String
:
Diff = "Use me to access really cool methods"
def Diff.patch
# ...
end
您可以执行这些操作中的任何一个,并且都可以使用,但是将相关方法分组的最佳方法是在Module
中作为普通实例方法(即,不使用self.
):
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 (i.e. without 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
行,它可以调用Diff.patch
. - 即使在全局名称空间中也使用这些方法
- use this functionality from within any Class (with
include Diff
) or from any object (withextend Diff
) - an example of this use is the
extend self
line which makes it possible to callDiff.patch
. - even use these methods in the global namespace
例如,在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
)一起导入,而不是单例方法.只有子类可以继承实例和单例方法.
Note: the extend self
will "modify" the Diff
module object itself but it won't have any effect on inclusions of the module. Same thing happens for a def self.foo
, the foo
won't be available to any class including it. In short, only instance methods of Diff
are imported with an include
(or an extend
), not the singleton methods. Only subclassing a class will provide inheritance of both instance and singleton methods.
当您实际上希望包含一个模块来提供实例方法和单例方法时,这并不完全容易.您必须使用self.included
挂钩:
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:
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
这篇关于使用Class vs Module在Ruby中打包代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!