如何向 Enumerable 模块添加方法?
How to add methods to the Enumerable module?
如何将自定义方法添加到 Ruby 中现有的 Enumerable 模块?我正在运行 Ruby 2.0.
与您向每个其他模块添加方法的方式相同。
如果你想添加带有参数 baz
和 quux
的方法 bar
到模块 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
在Ruby中可以使用monkey-patching
,其中包含了open classes
的概念。这意味着 Ruby 中的 classes 可以随时修改。例如,您可以在数字 class.
中创建一个 double 方法
class Integer < Numeric
def self.double
self * 2
end
end
现在您可以对数字调用 double 方法
4.double
=> 8
希望对您有所帮助
Enumerable
模块中定义的所有方法都要求接收者是枚举器或具有方法 each
。假设我们希望创建一个类似于 Enumerable#to_a 的可枚举方法 my_to_a
除了它 return 只是接收者元素的第一个 n
(或者,如果它是一个枚举器,则它生成的第一个 n
个元素),n
是 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
如果 self
是枚举数, 将 enum
设置为 self
,否则设置为 self.each
。后一种情况假设 self
有一个方法 each
,这意味着 class self.class
有一个实例方法 each
(或者方法 each
有已在 self
的单例 class 上定义)。 each
必须 return 一个枚举器。在该示例中,is_a?(Enumerator)
(相当于 self.is_a?(Enumerator)
)仅对于使用 String#gsub 且没有块的两个示例 true
1 在其他示例中 self.class.included_modules.includes?(Enumerable) #=> true
和 self.class.instance_methods.include?(:each) #=> true
。这些 class 是 Array
、Range
、Hash
和 Prime
。 each
是前三个的实例方法,Prime
的class方法。
一旦我们有了枚举器 enum
行
n.times.with_object([]) { |o,a| a << enum.next }
很简单。参见 Integer#times, Enumerator#with_object and Enumerator#next。
1 请注意 Enumerator.included_modules #=> [Enumerable, Kernel]
,因此任何 return 枚举器的方法(Enumerator
的实例)都会响应 Enumerable
方法。即不需要方法的class(比如String)包含Enumerable
或者有方法each
.
如何将自定义方法添加到 Ruby 中现有的 Enumerable 模块?我正在运行 Ruby 2.0.
与您向每个其他模块添加方法的方式相同。
如果你想添加带有参数 baz
和 quux
的方法 bar
到模块 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
在Ruby中可以使用monkey-patching
,其中包含了open classes
的概念。这意味着 Ruby 中的 classes 可以随时修改。例如,您可以在数字 class.
class Integer < Numeric
def self.double
self * 2
end
end
现在您可以对数字调用 double 方法
4.double
=> 8
希望对您有所帮助
Enumerable
模块中定义的所有方法都要求接收者是枚举器或具有方法 each
。假设我们希望创建一个类似于 Enumerable#to_a 的可枚举方法 my_to_a
除了它 return 只是接收者元素的第一个 n
(或者,如果它是一个枚举器,则它生成的第一个 n
个元素),n
是 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
如果 self
是枚举数, 将 enum
设置为 self
,否则设置为 self.each
。后一种情况假设 self
有一个方法 each
,这意味着 class self.class
有一个实例方法 each
(或者方法 each
有已在 self
的单例 class 上定义)。 each
必须 return 一个枚举器。在该示例中,is_a?(Enumerator)
(相当于 self.is_a?(Enumerator)
)仅对于使用 String#gsub 且没有块的两个示例 true
1 在其他示例中 self.class.included_modules.includes?(Enumerable) #=> true
和 self.class.instance_methods.include?(:each) #=> true
。这些 class 是 Array
、Range
、Hash
和 Prime
。 each
是前三个的实例方法,Prime
的class方法。
一旦我们有了枚举器 enum
行
n.times.with_object([]) { |o,a| a << enum.next }
很简单。参见 Integer#times, Enumerator#with_object and Enumerator#next。
1 请注意 Enumerator.included_modules #=> [Enumerable, Kernel]
,因此任何 return 枚举器的方法(Enumerator
的实例)都会响应 Enumerable
方法。即不需要方法的class(比如String)包含Enumerable
或者有方法each
.