2006年08月04日
_ __send__ と Methodクラス
今回は __send__ と Method クラスについてです。 senf、__send__はメソッド名を表す文字列もしくはシンボルで、任意のメソッドを 起動するメソッドです。 sendは例えばメールクラスを作ったときなどに使いたい名前でしょうから、 基本的には __send__ を使ったほうが良いでしょう。
"foo,bar,baz".__send__(:split, /,/) # => ["foo", "bar", "baz"]
などとして利用します。 このメソッドは「メソッド」もしくは「メソッド名」を抽象するために使えます。 利用法は多岐に渡りますが、ここでは例えばSymbol#to_procなどが挙げられるでしょう。
class Symbol def to_proc proc{|*args| reciever = args.shift; reciever.__send__(*args)} end end
以前この日記で書いたSymbol#[]というかbindも 一つの例として挙げられます。 他にも例えばdrubyなどで使われます。他の利用方として、 次回にはdefine_methodと組み合わせる例も出す予定です。
またこれと関連するものにMethodクラスがあります。 これはC#のdelegateみたいなものです。メソッドとレシーバの組を持つ オブジェクトで、callメソッドでそのメソッドの呼出しができます。
m = "foo, bar, baz".method(:split) m.call(/,/) # => ["foo", " bar", " baz"] m.call(/ /) # => ["foo,", "bar,", "baz"]
とこのように利用できます。 手続きオブジェクトのほうが汎用的に利用できるため、こちらはあまり利用されません。 ただ、環境を保存しなくてよい分だけ手続きオブジェクトより生成に必要なコストは 小さいという利点があります。 また、to_procメソッドを持っているため、
filenames.all?{|filename| valid?(filename)}
を
filenames.all?(&method(:valid?))
などと書くこともできます。
他にもUnboundMethodというのがあるのですが、正直使ったことがありません。 メソッドを「名前」ではなく「実体」で持ち運びたいときに利用するのでしょう。
次回はdefine_method、Rubyの世界を大きく広げてくれるこのメソッドについて 書こうかと思います。
面白いです。勉強会でやってみませんか?
じゃあそのうちにでも