3

Facets API を調べて、いくつかのメソッドを選択して、改良と互換性のあるパッチ ライブラリに含めます。

カーネルにパッチを当てようとして失敗しました。これはモジュールですが、私がパッチを当てた他のものはクラス (文字列、配列など) でした。


コアクラスに対する私の標準的なアプローチを使用して洗練できないことの証明は次のとおりです。

module Patch
  refine Kernel do
    def patched?
      true
    end
  end
end

# TypeError: wrong argument type Module (expected Class)
# from (pry):16:in `refine' 

また、カーネル モジュールをクラスにラップし、カーネルへのグローバル参照をそのクラスに変更しようとしました。

class MyKernel
  include Kernel
  extend Kernel
end

# not sure if Object::Kernel is really the global reference
Object::Kernel = MyKernel

module Patch
  refine MyKernel do
    def patched?
      true
     end
  end
end

class Test
  using Patch
  patched?
end
# NoMethodError: undefined method `patched?' for Test:Class
# from (pry):15:in `<class:Test>'

この場合、Kernel を Object に置き換えることで、同じ機能を正常に取得できました。

module Patch
  refine Object do
    def patched?
      true
     end
  end
end

class Test
  using Patch
  patched?
end

しかし、Enumerable などの他のコア モジュールでこの同等性を得ることができるかどうかはわかりません。

4

2 に答える 2

5

モジュールはruby​​ 2.4 以降で改良できます:

Module#refineモジュールを引数として受け入れるようになりました。[機能#12534 ]

古い警告(「洗練はモジュールではなくクラスのみを変更するため、引数はクラスでなければならない」) は適用されなくなりました (ただし、ruby​​ 2.6までドキュメントから削除されませんでした)。

module ModuleRefinement
  refine Enumerable do
    def tally(&block)
      block ||= ->(value) { value }
      counter = Hash.new(0)
      each { |value| counter[block[value]] += 1 }
      counter
    end
  end
end

using ModuleRefinement

p 'banana'.chars.tally # => {"b"=>1, "a"=>3, "n"=>2}
于 2019-03-02T20:25:46.113 に答える