[英]Changing method behaviour in ruby
Here is a code sample from the ruby pickaxe book: 以下是ruby pickaxe书中的代码示例:
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'
What I am having a hard time understanding is where the modified 'each' method comes into play? 我很难理解的是修改后的“每种”方法发挥作用的地方? I assume inject is calling it at some point but don't understand why it's doing it, and how I could predict or emulate this behavior in my code. 我假设inject在某个时候调用它但是不明白它为什么这样做,以及我如何在我的代码中预测或模拟这种行为。
Thanks! 谢谢!
The call to inject
actually causes a call to each
. 对inject
的调用实际上会导致对each
调用。 The way inject
works is by going over all the elements of the Enumerable
using each
, applying the passed operator to the memo
and to the next value and storing the result back into memo
. inject
的方式是使用each
元素遍历Enumerable
所有元素,将传递的操作符应用于memo
和下一个值,并将结果存储回memo
。 The result of the entire call is the value of memo
in the end. 整个调用的结果是最后的memo
的值。 You can see the documentation in here . 您可以在此处查看文档。
the VowelFinder
class implements the protocol that is mandatory for the Enumerable
module that you can include to gain a lot of ruby iterator methods: http://apidock.com/ruby/Enumerable VowelFinder
类实现了Enumerable
模块必需的协议 ,您可以包含该协议以获得许多ruby 迭代器方法: http : //apidock.com/ruby/Enumerable
The Enumerable mixin provides collection classes with several traversal and searching methods, and with the ability to sort. Enumerable mixin为集合类提供了多种遍历和搜索方法,并具有排序功能。 The class must provide a method each, which yields successive members of the collection. 该类必须提供每个方法,它产生集合的连续成员。 If Enumerable#max, #min, or #sort is used, the objects in the collection must also implement a meaningful <=> operator, as these methods rely on an ordering between members of the collection. 如果使用Enumerable#max,#min或#sort,则集合中的对象还必须实现有意义的<=>运算符,因为这些方法依赖于集合成员之间的顺序。
You are correct that inject actually calls each method and the reason this happens is because inject actually uses each method internally. 你是正确的,实际上注入每个方法,这是因为注入实际上在内部使用每个方法。 In fact, a lot if the Enumerable methods use the .each method; 事实上,如果Enumerable方法使用.each方法,那就很多了; like #map, #select, #reject. 比如#map,#select,#reject。
The reason for this is that .each is the actual method which allows looping in an Enumerable Object. 原因是.each是允许在Enumerable Object中循环的实际方法。 The other methods are just so that things get easy for us, developers, and we don't have to use .each everywhere. 其他方法只是让我们开发人员变得容易,而且我们不必在任何地方使用.each。 Imagine having to write the above code using .each. 想象一下,必须使用.each编写上面的代码。 It wouldn't be tough but vf.inject(:+) is definitely easier. 这不会很难,但vf.inject(:+)肯定更容易。 So is the case with collect or map. 收集或地图的情况也是如此。
And the best way to implement this(as is done in Ruby) without repeating code is to have the other method call #each as there is no code duplication and each of #map or #collect or #inject does not have to traverse the Enumerable Object differently. 在没有重复代码的情况下实现它的最佳方法(就像在Ruby中完成的那样)是让另一个方法调用#each,因为没有代码重复,#map或#collect或#inject中的每一个都不必遍历Enumerable对象不同。
Genrally, I avoid using #each and there are so many other methods which makes our job easier. 一般来说,我避免使用#each,还有很多其他方法可以让我们的工作更轻松。 If you want to modify your array collection, it's advisable not to money-patch the #each method (unless, of course, you want all the other methods to change as well.) 如果你想修改你的数组集合,建议不要对#each方法进行补贴(当然,除非你想要改变所有其他方法。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.