1

我是红宝石的新手。有没有办法用method_missing编写一个'def Array/Range/Hash',它适用于所有Range、Arrays和Hash,即所有Enumerables?例如,以下应该工作:

[1..5].Sum()  
[1,2,3,5].Sum()  
{'x' => 1, 'y' = 4}.Sum()  

Sum() 是我们在 method_missing 中定义的自定义方法。到目前为止,我已经编写了三个不同的函数,分别处理 Array、Range 和 Hash 的 method_missing。

4

2 回答 2

4

您可以通过打开模块并向其添加实例方法来定义method_missing所有 Enumerables :Enumerable

module Enumerable
  def method_missing *args
    puts 'hi'
  end
end

[].hithere # => hi

但我建议定义具体sum方法(以小写字母开头,根据 Ruby 方法命名指南),而不是将此逻辑添加到method_missing

module Enumerable
  def sum
    # your implementation
  end
end

[].sum
于 2012-03-11T10:28:43.957 回答
0

正如亚历克斯所说,最好的方法是为 Enumerable 定义自己的方法#sum,但是,虽然每个 Enumerable 都应该有#each,但每个子类产生的结果是不同的。例如 Hash 产生一个键值对,您的单个 #sum 方法必须知道如何处理。

这是它如何做到这一点的一个示例,它尝试将传入的参数放入一个数组中,并且总和仅包括数组的最后一个元素。这适用于哈希、数组和范围(但它可能只适用于 1.9)

module Enumerable
  def sum
    r = 0
    each {|(*x)| r += x.last}
    r
  end
end

或者,您可以为每个 Enumerable 定义自己的迭代方法,例如 #each_for_sum 并让 #sum 使用该方法进行求和。但是您可能必须为不同的 Enumerables 编写多个版本的#each_for_sum(例如,默认的#each_for_sum 将只是 Enumerable#each,但 Hash#each_for_sum 只会产生值)。

module Enumerable
  def sum
    r = 0
    each_for_sum {|x| r += x}
    r
  end

  def each_for_sum &block
     each(&block)
  end
end

class Hash
  def each_for_sum
    values.each {|x| yield x}
  end
end
于 2012-03-11T10:52:43.313 回答