ruby での改良の現在の実装に関する非常に優れたドキュメントが http://ruby-doc.org//core-2.2.0/doc/syntax/refinements_rdoc.htmlにありますが、奇妙なケースがいくつかあります。
まず、include module
直交してusing module
います (1 つはモジュールのインスタンス メソッドを含み、もう 1 つはリファインメントをアクティブにします)。しかし、絞り込みモジュール自体を含めるトリックがあります。「
絞り込みを使用するよりも Ruby クラスをモジュールに変換する方法が優れていますか?」を参照してください。.
def to_module(klass)
Module.new do
#note that we return the refinement module itself here
return refine(klass) {
yield if block_given?
}
end
end
class Base
def foo
"foo"
end
end
class Receiver
include to_module(Base) {
def foo
"refined " + super
end
}
end
Receiver.new.foo #=> "refined foo"
using
奇妙なことに、この改良モジュールは!では使用できません。
m=to_module(Base) {}
m.class #=> Module
using m
#=>TypeError: wrong argument type Class (expected Module)
したがって、洗練モジュールの囲みモジュールでのみ作業を使用します。次に、 https://www.new-bamboo.coのように Proc をソースに戻すことに頼らずに、上記の yield トリックを使用して Proc を渡して (ブロックのみを受け入れても) 洗練させたいと考えました
。 .uk/blog/2014/02/05/refinements-under-the-knife/ . ただしyield
、インクルードの例のように使用しても機能しません。
def ref_module1(klass)
Module.new do
refine(klass) {
yield
}
end
end
class Receiver1
using ref_module1(Base) {
def foo
"refined " + super
end
}
def bar
Base.new.foo
end
end
Receiver1.new.bar #=> NoMethodError: super: no superclass method `foo'
Receiver1 は依然として Bar#foo を使用しており、洗練されたメソッドを使用していないことがわかります。module_eval
ただし、代わりに使用できます。
def ref_module2(klass,&b)
Module.new do
refine(klass) {
module_eval(&b)
}
end
end
class Receiver2
using ref_module2(Base) {
def foo
"refined " + super
end
}
def bar
Base.new.foo
end
end
Receiver2.new.bar #=> "refined foo"
module_eval
メソッドではなく、なぜここで機能するのかよくわかりませんyield
。改良ブロック内では、'default_definee' が改良モジュールであるためmodule_eval
、'default_definee' をself
='改良モジュール' に配置しても影響を受けません。実際、冒頭の「include」の例では、module_eval
or を直接使用しても同じ結果が得られyield
ます。
誰でもこの動作を説明できますか?