3

私は次のようにEnumerableモジュールのメソッドを上書きしようとしています:

module Enumerable
  def collect(&block)
    puts 'collect'
    super
  end
end

(これは簡単な例であることに注意してください)。

理論的には、collectまたはを呼び出すときmap、Rubyはオーバーライドされたバージョンを使用する必要がありますよね?しかし、そうではありません。常に組み込みのEnumerableメソッドを使用します。それcollectは実際enum_collectにソースに準拠しているからですか?

[1,2,3].map(&:to_s) # never prints anything

はい、モンキーパッチが悪いなど、サブクラス化などの選択肢があることは承知していますが、組み込みのC関数をRubyで上書きできるかどうか知りたいです。

Enumerable.class_eval do
  def collect(&block)
    puts 'collect was class_eval'
    super
  end
end

 

eigen = class << Enumerable; self; end
eigen.class_eval do
  def collect(&block)
    puts 'collect was eigen'
    super
  end
end

 

module Enumerable
  def collect(&block)
    puts 'collect was opened up'
    super
  end
end

 

Array.send(:include, Enumerable)

そしてそのほとんどすべての組み合わせ。

PS。これはRuby1.9.3ですが、理想的にはすべてのバージョンで機能するソリューションを探しています。

4

2 に答える 2

5

あなたの問題は、ArrayがEnumerableを使用するのではなく、独自のcollectメソッドを定義することだと思います。

収集{|アイテム| ブロック}→new_ary
マップ{|アイテム| ブロック}→new_ary
収集→an_enumerator
マップ→an_enumerator

の要素ごとに1回ブロックを呼び出しますself。ブロックによって返される値を含む新しい配列を作成します。も参照してくださいEnumerable#collect

したがって、必要なEnumerable#collectすべてのモンキーパッチを適用できますが、Arrayを使用しないため、気にしませんEnumerable#collect。モンキーパッチを適用すると、運が良くなりますArray#collect

class Array
  def collect
    #...
  end
end

Array#map同様にパッチを適用するか、単にパッチmapを適用してエイリアスに処理させることをお勧めしますcollect

Array#mapこれはCで実装されているため、C部分は問題とは関係がないことに注意してください。

于 2012-12-30T01:19:58.870 に答える
0

同じメソッドのセットを使用して、Rubyのさまざまなタイプのオブジェクトを反復処理できます。たとえば、インクルードを使用できますか?配列とハッシュを反復処理して特定のオブジェクトが含まれているかどうかを確認し、同様にmapメソッドを使用してそれらを変換するメソッド。それぞれのメソッドがこれらのメソッド自体を実装していると思うかもしれませんが、それは間違いです。

Rubyでは、これらのタイプのメソッドはEnumerableモジュールに実装されています。クラスが各メソッドを実装し、Enumerableモジュールを含む場合、クラスは、反復、マッピング、検索など、コレクションを含むメッセージのホスト全体に応答します。

于 2014-07-31T17:14:03.147 に答える