refined(*modules) -> ProcRuby 4.1 から[permalink][rdoc][edit]-
selfと同じように振る舞いつつ、本体の中でmodulesの各モジュールによって有効化される refinement が効く新しいProcを返します。selfは変更されません。modulesを 1 つも指定しなかった場合はselfを返します。このメソッドの呼び出しを連鎖させた場合、指定したすべてのモジュールが指定した順序で有効になります。そのため、後の呼び出しで有効にした refinement が優先されます。
refinement は本体全体で有効で、本体の中でネストしたブロックや、本体の中で
defで定義したメソッドにも及びます。usingの効く範囲の中でdefしたメソッドと同様に、そのようなメソッドは後で呼び出されたときも refinement を保持し続けます。返された
Procの refinement の集合は生成時に固定されます。その本体の中でusingを呼び出すと RuntimeError が発生します。返された
Procを実行するには、selfに影響を与えずに refinement を通してメソッドを解決できるように、そのブロックとネストしたすべてのブロックの命令シーケンスのコピーが必要です。コピーは返されたProcが初めて呼び出されたときに作られ、同じブロックと同じモジュールの組み合わせ(1 回の呼び出しでも連鎖した呼び出しでも)に対してキャッシュされて再利用されます。一度も呼び出されないProcはコピーされません。そのため refinement を適用すると、Procを実行した時点でブロックの大きさにおおむね比例してメモリ使用量が増えます。- [PARAM]
modules: - 有効にする refinement を定義した Module を任意個指定します。
- [EXCEPTION]
TypeError: -
modulesに Module 以外を指定した場合に発生します。 - [EXCEPTION]
ArgumentError: -
selfが Ruby のブロックから作られたProcでない場合(C 関数・Symbol・Method から変換されたProcなど)に発生します。
module StringRefinement refine String do def shout = upcase + "!" end end original = ->(s) { s.shout } refined_proc = original.refined(StringRefinement) p refined_proc.call("hi") # => "HI!" original.call("hi") # ~> NoMethodError[SEE_ALSO] Module#refine, main.using
- [PARAM]