1
module Ext
  refine Hash do
    def foo
      puts :in_foo
    end
    def bar
      puts :in_bar
      foo
    end
  end
end
module Test
  using Ext
  Hash.new.bar
end
# in_bar
# in_foo
# => nil

これは期待どおりに機能します。しかし、を使用してfoobarの間Hashで とを共有したい場合、失敗します。Arrayinclude

module Shared
  def foo
    puts :in_foo
  end
  def bar
    puts :in_bar
    foo
  end
end
module Ext
  refine Hash do
    include Shared
  end
  refine Array do
    include Shared
  end
end
module Test
  using Ext
  Hash.new.bar
end
# in_bar
# NameError: undefined local variable or method `foo' for {}:Hash

リファインメント間でコードを共有する方法はありますか?

4

1 に答える 1

0

問題は共有ではありません。洗練を完全に取り除くとArray、同じ動作が得られます。

ドキュメントに従って:

絞り込みは、それぞれファイルの終わりまたは eval 文字列の終わりまでアクティブです。絞り込みは範囲内で語彙的です。制御がスコープの外に移されると、改良は無効になります。これは、現在のスコープ外で定義されているファイルを要求またはロードするか、メソッドを呼び出すと、絞り込みが無効になることを意味します。

つまり、あなたの例で失敗するのはrefine do ⇒ include. この言語は文節include内を理解する準備ができていません。refine将来、機能が「実験的」段階から抜け出すときに、それが可能になるかもしれません.

それでもrefinemenetsに頼りたいと思う場合は、ルビをごまかすかもしれません(グローバルはアイデアを明確にするためです):

$ref = lambda do
  def foo
    puts :in_foo
  end
  public :foo
  def bar
    puts :in_bar
    foo
  end
  public :bar
end
module Ext
  refine ::Hash do
    $ref.call
  end
end
module Test
  using Ext
  ::Hash.new.bar
end

#⇒ in_bar
#⇒ in_foo
于 2015-06-28T10:41:08.360 に答える