obj.method(:method_name) によりオブジェクト化され たメソッドオブジェクトのクラスです。メソッドの実体(名前でなく)とレシー バの組を封入します。Proc オブジェクトと違ってコンテキストを保持 しません。
Proc との差…Method
は取り出しの対象であるメソッドが
なければ作れませんが、Proc
は準備なしに作れます。その点から
Proc
は使い捨てに向き、Method
は何度も繰り返し生成する
場合に向くと言えます。また内包するコードの大きさという点では
Proc
は小規模、Method
は大規模コードに向くと言えます。
例:
既存のメソッドを Method オブジェクト化する (Object#method を参照)
class Foo def foo(arg) "foo called with arg #{arg}" end end m = Foo.new.method(:foo) p m # => #<Method: Foo#foo> p m.call(1) # => "foo called with arg 1"
名前のないメソッド(の代わり)が必要なら Proc を使うと良い
pr = Proc.new {|arg| "proc called with arg #{arg}" } p pr # => #<Proc:0x401b1fcc> p pr.call(1) # => "proc called with arg 1"
Method オブジェクトが有用なのは以下のような場合
class Foo def foo() "foo" end def bar() "bar" end def baz() "baz" end end obj = Foo.new # 任意のキーとメソッドの関係をハッシュに保持しておく methods = {1 => obj.method(:foo), 2 => obj.method(:bar), 3 => obj.method(:baz)} # キーを使って関連するメソッドを呼び出す p methods[1].call # => "foo" p methods[2].call # => "bar" p methods[3].call # => "baz"
が、レシーバを固定させる(Method オブジェクトはレシーバを保持する)必 要がないなら Object#sendを使う方法も有用。
class Foo def foo() "foo" end def bar() "bar" end def baz() "baz" end end # 任意のキーとメソッド(の名前)の関係をハッシュに保持しておく # レシーバの情報がここにはないことに注意 methods = {1 => :foo, 2 => :bar, 3 => :baz} # キーを使って関連するメソッドを呼び出す # レシーバは任意(Foo クラスのインスタンスである必要もない) p Foo.new.send(methods[1]) # => "foo" p Foo.new.send(methods[2]) # => "bar" p Foo.new.send(methods[3]) # => "baz"
self[arg, ...]
call(arg ... )
call(arg ... ) { ... }
メソッドオブジェクトに封入されているメソッドを起動します。 引数やブロックはそのままメソッドに渡されます。
self[]
の形の呼び出しは通常のメソッド呼び出しに見た目を
近付けるためだけに用意されたもので、Array#[]のような
他の [] メソッドとの意味的な関連性はありません。
メソッドオブジェクトが汚染されている場合、そのメソッドは、セーフレ ベル 4 で実行されます (セーフレベルに関するその他の詳細を参照)。
arity
メソッドオブジェクトの引数の数を返します。self
が引数の数を
可変長で受け取れる場合
-(最低限必要な数 + 1)
を返します。
inspect
Object#inspect 参照。以下の形式の文字列を返し ます。
#<Method: klass1(klass2)#method> (形式1)
klass1 は、Method#inspect では、レシーバのクラス名、 UnboundMethod#inspect では、UnboundMethod オブジェクトの生成 元となったクラス/モジュール名です。
klass2 は、実際にそのメソッドを定義しているクラス/モジュール名、 method は、メソッド名を表します。
module Foo def foo "foo" end end class Bar include Foo def bar end end p Bar.new.method(:foo) # => #<Method: Bar(Foo)#foo> p Bar.new.method(:bar) # => #<Method: Bar(Bar)#bar>
ruby 1.7 feature: klass1 と klass2 が同じ場合は以下の形式になります。
#<Method: klass1#method> (形式2)
ruby 1.7 feature: 特異メソッドに対しては、
#<Method: obj.method> (形式3) #<Method: klass1(klass2).method> (形式4)
という形式の文字列を返します。二番目の形式では klass1 はレシーバ、 klass2 は実際にそのメソッドを定義しているオブジェクトになります。
# オブジェクトの特異メソッド obj = "" class <<obj def foo end end p obj.method(:foo) # => #<Method: "".foo> # クラスメソッド(クラスの特異メソッド) class Foo def Foo.foo end end p Foo.method(:foo) # => #<Method: Foo.foo> # スーパークラスのクラスメソッド class Bar < Foo end p Bar.method(:foo) # => #<Method: Bar(Foo).foo> # 以下は(形式1)の出力になる module Baz def baz end end class <<obj include Baz end p obj.method(:baz) # => #<Method: Object(Baz)#baz>
to_proc
self
を call
する Proc オブジェクトを生成して返
します。
unbind
self
のレシーバとの関連を取り除いた UnboundMethod オブ
ジェクトを生成して返します。