如何将方法添加到Enumerable模块?

时间:2015-01-01 22:04:33

标签: ruby module enumerable

如何将自定义方法添加到Ruby中的现有Enumerable模块?我正在运行Ruby 2.0。

3 个答案:

答案 0 :(得分:3)

将方法添加到每个其他模块的方法相同。

如果您要将带有参数barbaz的方法quux添加到模块Foo,请编写

module Foo
  def bar(baz, quux)
    # code code code
  end
end

因此,如果要将方法histogram添加到模块Enumerable,请编写

module Enumerable
  # Counts the number of occurrences of each unique object in `self`.
  #
  # @return [Hash<E, Integer>] a `Hash` of objects mapped to number of occurrences in `self`.
  def histogram
    group_by(&:itself).map {|k, v| [k, v.size] }.to_hash
  end
end

答案 1 :(得分:2)

在Ruby中,您可以使用monkey-patching,其中包含open classes的概念。这意味着Ruby中的类可以随时修改。例如,您可以在数字类中创建一个double方法。

class Integer < Numeric
  def self.double
    self * 2
  end
end

现在你可以在数字上调用双重方法

4.double
=> 8

希望这有帮助

答案 2 :(得分:0)

Enumerable模块中定义的所有方法都要求接收者是枚举数或具有方法each。假设我们希望创建一个类似于Enumerable#to_a的可枚举方法my_to_a,除了它只返回接收者元素的第一个n(或者,如果它是一个枚举器,则返回第一个{{1} }元素),nn的参数。

my_to_a

module Enumerable
  def my_to_a(n)
    enum = is_a?(Enumerator) ? self : each
    n.times.with_object([]) { |o,a| a << enum.next }
   end
end

[0,1,2,3,4].my_to_a(3)
  #=> [0, 1, 2] 
(0..4).my_to_a(3)
  #=> [0, 1, 2] 
{ a:1, b:2, c:3, d:4, e:5 }.my_to_a(3)
  #=> [[:a, 1], [:b, 2], [:c, 3]] 
'0ab_1ab_2ab_3ab_4ab'.gsub(/.(?=ab)/).my_to_a(3)
  #=> ["0", "1", "2"] 
require 'prime'; Prime.my_to_a(4)
  #=> [2, 3, 5, 7] 
[0,1,2,3,4].my_to_a(6)
  #=> StopIteration (iteration reached an end)
'0ab_1ab_2ab_3ab_4ab'.gsub(/.(?=ab)/).my_to_a(6)
  #=> StopIteration (iteration reached an end)
如果enum = is_a?(Enumerator) ? self : each 是枚举器,

enum设置为self,否则将其设置为枚举器self。后一种情况假设self.each具有方法self,这意味着类each具有实例方法self.class(或方法each已在{ {1}}的单例课程)。 each必须返回一个枚举数。在此示例中,self(等效于each)仅对于使用String#gsub且有一个参数且没有块的两个示例为is_a?(Enumerator) 1 在其他示例中,self.is_a?(Enumerator)true。这些类是self.class.included_modules.includes?(Enumerable) #=> trueself.class.instance_methods.include?(:each) #=> trueArrayRangeHash是前三个实例方法,Prime是类方法。

一旦我们有了枚举数each

Prime

很简单。参见Integer#timesEnumerator#with_objectEnumerator#next

1注意enum,因此任何返回枚举数的方法(实例为n.times.with_object([]) { |o,a| a << enum.next } )都会对Enumerator.included_modules #=> [Enumerable, Kernel]方法作出响应。也就是说,方法的类(例如String)无需包含Enumerator或具有方法Enumerable