简体   繁体   English

更改ruby中的方法行为

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM