繁体   English   中英

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

[英]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 你的问题的假设是你不想实例化任何东西,所以我建议你只使用一个模块。

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

在您的两个示例中,您实际上并未在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 )中使用此功能
  • 这种用法的一个例子是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中,类是一种模块。

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

以下也有效

Matrix = Object.new

def Matrix.add ...
def Matrix.equals ...

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM