我不明白为什么在这段代码中定义 each
方法:
class VowelFinder
include Enumerable
def initialize(string)
@string = string
end
def each
@string.scan(/[aeiou]/) do |vowel|
yield vowel
end
end
end
vf = VowelFinder.new("the quick brown fox jumped")
vf.inject(:+)
# => "euiooue"
此代码有效,但不是没有 each
. 另外,如果我使用 Array
和 Range
类,并在其中覆盖 each
方法,则会发生不同的事情 .
当我创建一个对象,并在其上调用 inject
方法时, each
方法何时以及如何工作?
1 回答
TL:DR Enumerable mixin和你签订了一份 Contract . 你告诉它
each
的意思,它带来了几十种额外的方法 .inject
是其中一种方法 .实际讨论
inject
如何运作?粗略地说,它遍历由元素组成的东西,在元素到达时将元素应用于元素 . 字符串"the quick brown fox jumped"
的元素是什么?可以说,它们是它的角色 . 因此,如果我们将字符串视为一个字符数组并注入连接字符串的+
,我们希望得到原始字符串本身:但现在让我们更进一步 . Ruby有mixins,特别是它有Enumerable mixin . 这允许我们将任何我们喜欢的东西视为"something that has elements" . 因此,不要使用数组,让我们可以在字符串本身的元素上注入
+
. 为此,我们必须为String定义each
,以便可以遍历字符串的元素 . 一旦我们这样做,Enumerable的许多方法,包括inject
,将会生动 .each
对于一个字符串应该是什么意思?再一次,我们可以简单地说它意味着每个角色 . 我们可以想象通过将each
别名到现有的each_char
来做到这一点:但是我们可以从头开始定义
each
,而不是将each
别名化为each_char
. 我们已经知道了一种方法,使用scan
:但是
each
的定义取决于我,所以不是扫描每个角色,我可以扫描其他一些模式!例如,我可以扫描元音:但是,通过以这种奇怪的方式定义
each
,我们不要蹩脚 . 让's sluff this whole functionality off onto a custom class. Let'称它为VowelFinder!因此,我们最终得到了您开始使用的代码 .