何时使用模块,何时使用类

时间:2010-04-19 23:13:02

标签: ruby class module

我目前正在阅读Gregory Brown Ruby Best Practices一书。在早期,他正在讨论从相关类的辅助方法重构某些功能,到模块上的某些方法,然后使用模块extend self

之前没有看到过,在快速谷歌之后,发现模块上的extend self允许模块上定义的方法相互看见,这是有道理的。

现在,我的问题是你什么时候会做这样的事情

module StyleParser
  extend self

  def process(text)
    ...
  end

  def style_tag?(text)
    ...
  end
end

然后在

的测试中引用它
@parser = Prawn::Document::Text::StyleParser

而不是像这样的东西?

class StyleParser

  def self.process(text)
    ...
  end

  def self.style_tag?(text)
    ...
  end
end 

是否可以将它用作mixin?还是有其他原因我没看到?

3 个答案:

答案 0 :(得分:38)

类应该用于需要实例化或需要跟踪状态的功能。模块既可以用作将功能混合到多个类中的方式,也可以用作提供不需要实例化或跟踪状态的一次性功能的方法。类方法也可以用于后者。

考虑到这一点,我认为区别在于你是否真的需要一堂课。当您拥有需要某些单例功能的现有类时,类方法似乎更合适。如果您所做的只包含单例方法,那么将它作为模块实现并通过模块直接访问它会更有意义。

答案 1 :(得分:7)

在这种特殊情况下,我可能既不会使用类也不会使用模块。

一个类是对象的工厂(注意复数)。如果您不想创建该类的多个实例,则不需要它存在。

模块是方法的容器,在多个对象之间共享。如果不将模块混合到多个对象中,则不需要它存在。

在这种情况下,看起来你只想要一个对象。所以使用一个:

def (StyleParser = Object.new).process(text)
  ...
end

def StyleParser.style_tag?(text)
  ...
end

或者:

class << (StyleParser = Object.new)
  def process(text)
    ...
  end

  def style_tag?(text)
    ...
  end
end

但正如@Azeem已经写道:为了做出正确的决定,你需要更多的背景。我不太熟悉Prawn的内部人员,知道为什么Gregory做出了这个特别的决定。

答案 2 :(得分:-1)

如果您想要实例化,请使用类。你的问题的其余部分需要更多的背景才有意义。