如何在班上使用Enumerable mixin?

ben*_*ben 51 ruby

我有一个名为的类Note,其中包含一个名为的实例变量time_spent.我希望能够做到这样的事情:

current_user.notes.inject{|total_time_spent,note| total_time_spent + note.time_spent}
Run Code Online (Sandbox Code Playgroud)

这可以通过在Enumerable模块中混合来实现吗?我知道你应该添加include Enumerable到类中然后定义一个each方法,但是每个方法应该是一个类还是实例方法?是什么在变each的方法?

我正在使用Ruby 1.9.2

Mic*_*ohl 87

这很简单,只需包含Enumerable模块并定义一个each实例方法,这通常会使用其他类的each方法.这是一个非常简化的例子:

class ATeam
  include Enumerable

  def initialize(*members)
    @members = members
  end

  def each(&block)
    @members.each do |member|
      block.call(member)
    end
    # or
    # @members.each(&block)
  end
end

ateam = ATeam.new("Face", "B.A. Barracus", "Murdoch", "Hannibal")
#use any Enumerable method from here on
p ateam.map(&:downcase)
Run Code Online (Sandbox Code Playgroud)

有关详细信息,我建议使用以下文章:Ruby Enumerable Magic:The Basics.

在您的问题的上下文中,如果您通过访问器公开的内容已经是一个集合,您可能不需要费心包括Enumerable.

  • 为什么不简单地`@ members.each(&block)`? (13认同)
  • @tokland为了每个人都了解这一点. (10认同)
  • @MichaelKohl:太好了,谢谢.是的,好吧,我可以编辑,但我认为首先评论更有礼貌,只有当用户无法访问时,才能编辑代码. (5认同)
  • @MichaelKohl:获得批准,新手最初可能会遇到一些问题,但是这是一个非常普遍的习惯用语,提及它并不会有什么害处.另请注意,以这种方式执行此操作可以免费获得"each"的默认行为:当没有发送块时,您将获得一个枚举器.如果您以另一种方式明确地产生或调用块,则会出现错误. (4认同)
  • 当我使用显式块参数时,我更喜欢使用proc对象.就个人而言,我通常使用`[]`别名来调用``block(`block [member]`),但是认为这可能会让OP感到困惑. (2认同)

3li*_*t0r 6

Enumerable文档说明如下

Enumerable mixin集合类提供了多种遍历和搜索方法,并具有排序功能。该类必须提供一个方法every,该方法生成集合的连续成员。如果使用Enumerable#max#min#sort ,则集合中的对象还必须实现有意义的<=>运算符,因为这些方法依赖于集合成员之间的排序。

each这意味着在集合上实施。如果您有兴趣使用#max,#min或者您应该在其成员上#sort实现。<=>

请参阅:可枚举