要約
Object#method によりオブジェクト化されたメソッドオブジェクトのクラスです。
メソッドの実体(名前でなく)とレシーバの組を封入します。 Proc オブジェクトと違ってコンテキストを保持しません。
Proc との差
Method は取り出しの対象であるメソッドがなければ作れませんが、Proc は準備なしに作れます。その点から Proc は使い捨てに向き、Method は何度も繰り返し生成する場合に向くと言えます。また内包するコードの大きさという点では Proc は小規模、Method は大規模コードに向くと言えます。
既存のメソッドを 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#public_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.public_send(methods[1]) # => "foo"
p Foo.new.public_send(methods[2]) # => "bar"
p Foo.new.public_send(methods[3]) # => "baz"
@see Object#method
目次
- インスタンスメソッド
インスタンスメソッド
self << callable -> Proc
[permalink][rdoc][edit]-
self と引数を合成した Proc を返します。
戻り値の Proc は可変長の引数を受け取ります。戻り値の Proc を呼び出すと、まず受け取った引数を callable に渡して呼び出し、その戻り値を self に渡して呼び出した結果を返します。
Method#>> とは呼び出しの順序が逆になります。
- [PARAM] callable:
- Proc、Method、もしくは任意の call メソッドを持ったオブジェクト。
def f(x) x * x end def g(x) x + x end # (3 + 3) * (3 + 3) p (method(:f) << method(:g)).call(3) # => 36
class WordScanner def self.call(str) str.scan(/\w+/) end end File.write('testfile', <<~TEXT) Hello, World! Hello, Ruby! TEXT pipeline = method(:pp) << WordScanner << File.method(:read) pipeline.call('testfile') # => ["Hello", "World", "Hello", "Ruby"]
self == other -> bool
[permalink][rdoc][edit]eql?(other) -> bool
-
自身と other が同じインスタンスの同じメソッドを表す場合に true を返します。そうでない場合に false を返します。
- [PARAM] other:
- 自身と比較したいオブジェクトを指定します。
s = "bar" a = s.method(:size) b = s.method(:size) p a == b #=> true
self[*args] -> object
[permalink][rdoc][edit]call(*args) -> object
call(*args) { ... } -> object
self === *args -> object
-
メソッドオブジェクトに封入されているメソッドを起動します。
引数やブロックはそのままメソッドに渡されます。
self[] の形の呼び出しは通常のメソッド呼び出しに見た目を近付けるためだけに用意されたもので、Array#[]のような他の [] メソッドとの意味的な関連性はありません。
- [PARAM] args:
- self に渡される引数。
[SEE_ALSO] UnboundMethod#bind_call
class Foo def foo(arg) "foo called with arg #{arg}" end end m = Foo.new.method(:foo) # => #<Method: Foo#foo> m[1] # => "foo called with arg 1" m.call(2) # => "foo called with arg 2"
self >> callable -> Proc
[permalink][rdoc][edit]-
self と引数を合成した Proc を返します。
戻り値の Proc は可変長の引数を受け取ります。戻り値の Proc を呼び出すと、まず受け取った引数を self に渡して呼び出し、その戻り値を callable に渡して呼び出した結果を返します。
Method#<< とは呼び出しの順序が逆になります。
- [PARAM] callable:
- Proc、Method、もしくは任意の call メソッドを持ったオブジェクト。
def f(x) x * x end def g(x) x + x end # (3 * 3) + (3 * 3) p (method(:f) >> method(:g)).call(3) # => 18
class WordScanner def self.call(str) str.scan(/\w+/) end end File.write('testfile', <<~TEXT) Hello, World! Hello, Ruby! TEXT pipeline = File.method(:read) >> WordScanner >> method(:pp) pipeline.call('testfile') # => ["Hello", "World", "Hello", "Ruby"]
arity -> Integer
[permalink][rdoc][edit]-
メソッドが受け付ける引数の数を返します。
ただし、メソッドが可変長引数を受け付ける場合、負の整数
-(必要とされる引数の数 + 1)
を返します。C 言語レベルで実装されたメソッドが可変長引数を受け付ける場合、-1 を返します。
class C def u; end def v(a); end def w(*a); end def x(a, b); end def y(a, b, *c); end def z(a, b, *c, &d); end end c = C.new p c.method(:u).arity #=> 0 p c.method(:v).arity #=> 1 p c.method(:w).arity #=> -1 p c.method(:x).arity #=> 2 p c.method(:y).arity #=> -3 p c.method(:z).arity #=> -3 s = "xyz" s.method(:size).arity #=> 0 s.method(:replace).arity #=> 1 s.method(:squeeze).arity #=> -1 s.method(:count).arity #=> -1
clone -> Method
[permalink][rdoc][edit]-
自身を複製した Method オブジェクトを作成して返します。
class Foo def foo "foo" end end m = Foo.new.method(:foo) # => #<Method: Foo#foo> m.call # => "foo" m.clone # => #<Method: Foo#foo> m.clone.call # => "foo"
curry -> Proc
[permalink][rdoc][edit]curry(arity) -> Proc
-
self を元にカリー化した Proc を返します。
カリー化した Proc はいくつかの引数をとります。十分な数の引数が与えられると、元の Proc に引数を渡し て実行し、結果を返します。引数の個数が足りないときは、部分適用したカリー化 Proc を返します。
- [PARAM] arity:
- 引数の個数を指定します。可変長の引数を指定できるメソッドをカリー化する際には必ず指定する必要があります。
def foo(a,b,c) [a, b, c] end proc = self.method(:foo).curry proc2 = proc.call(1, 2) #=> #<Proc> proc2.call(3) #=> [1,2,3] def vararg(*args) args end proc = self.method(:vararg).curry(4) proc2 = proc.call(:x) #=> #<Proc> proc3 = proc2.call(:y, :z) #=> #<Proc> proc3.call(:a) #=> [:x, :y, :z, :a]
[SEE_ALSO] Proc#curry
hash -> Integer
[permalink][rdoc][edit]-
自身のハッシュ値を返します。
a = method(:==) b = method(:eql?) p a.eql? b # => true p a.hash == b.hash # => true p [a, b].uniq.size # => 1
inspect -> String
[permalink][rdoc][edit]to_s -> String
-
self を読みやすい文字列として返します。
以下の形式の文字列を返します。
#<Method: klass1(klass2)#method(arg) foo.rb:2> (形式1)
klass1 は、Method#inspect では、レシーバのクラス名、 UnboundMethod#inspect では、UnboundMethod オブジェクトの生成元となったクラス/モジュール名です。
klass2 は、実際にそのメソッドを定義しているクラス/モジュール名、 method は、メソッド名を表します。
arg は引数を表します。「foo.rb:2」は Method#source_location を表します。 source_location が nil の場合には付きません。
module Foo def foo "foo" end end class Bar include Foo def bar(a, b) end end p Bar.new.method(:foo) # => #<Method: Bar(Foo)#foo() test.rb:2> p Bar.new.method(:bar) # => #<Method: Bar#bar(a, b) test.rb:8>
klass1 と klass2 が同じ場合は以下の形式になります。
#<Method: klass1#method() foo.rb:2> (形式2)
特異メソッドに対しては、
#<Method: obj.method() foo.rb:2> (形式3) #<Method: klass1(klass2).method() foo.rb:2> (形式4)
という形式の文字列を返します。二番目の形式では klass1 はレシーバ、 klass2 は実際にそのメソッドを定義しているオブジェクトになります。
# オブジェクトの特異メソッド obj = "" class <<obj def foo end end p obj.method(:foo) # => #<Method: "".foo() foo.rb:4> # クラスメソッド(クラスの特異メソッド) class Foo def Foo.foo end end p Foo.method(:foo) # => #<Method: Foo.foo() foo.rb:11> # スーパークラスのクラスメソッド class Bar < Foo end p Bar.method(:foo) # => #<Method: Bar(Foo).foo() foo.rb:11> # 以下は(形式1)の出力になる module Baz def baz end end class <<obj include Baz end p obj.method(:baz) # => #<Method: String(Baz)#baz() foo.rb:23>
[SEE_ALSO] Object#inspect
name -> Symbol
[permalink][rdoc][edit]-
このメソッドの名前を返します。
class Foo def foo(arg) "foo called with arg #{arg}" end end m = Foo.new.method(:foo) # => #<Method: Foo#foo> m.name # => :foo
original_name -> Symbol
[permalink][rdoc][edit]-
オリジナルのメソッド名を返します。
class C def foo; end alias bar foo end C.new.method(:bar).original_name # => :foo
[SEE_ALSO] UnboundMethod#original_name
owner -> Class | Module
[permalink][rdoc][edit]-
このメソッドが定義されている class か module を返します。
class Foo def foo(arg) "foo called with arg #{arg}" end end m = Foo.new.method(:foo) # => #<Method: Foo#foo> m.owner # => Foo m = Foo.new.method(:puts) # => #<Method: Foo(Kernel)#puts> m.owner # => Kernel
parameters -> [object]
[permalink][rdoc][edit]-
Method オブジェクトの引数の情報を返します。
Method オブジェクトが引数を取らなければ空の配列を返します。引数を取る場合は、配列の配列を返し、各配列の要素は引数の種類に応じた以下のような Symbol と、仮引数の名前を表す Symbol の 2 要素です。組み込みのメソッドでは、仮引数の名前が取れません。
- :req
-
必須の引数
- :opt
-
デフォルト値が指定されたオプショナルな引数
- :rest
-
* で指定された残りすべての引数
- :keyreq
-
必須のキーワード引数
- :key
-
デフォルト値が指定されたオプショナルなキーワード引数
- :keyrest
-
** で指定された残りのキーワード引数
- :block
-
& で指定されたブロック引数
m = Class.new{define_method(:m){|x, y=42, *other, k_x:, k_y: 42, **k_other, &b|}}.instance_method(:m) m.parameters #=> [[:req, :x], [:opt, :y], [:rest, :other], [:keyreq, :k_x], [:key, :k_y], [:keyrest, :k_other], [:block, :b]] File.method(:symlink).parameters #=> [[:req], [:req]]
[SEE_ALSO] Proc#parameters
receiver -> object
[permalink][rdoc][edit]-
このメソッドオブジェクトのレシーバを返します。
class Foo def foo(arg) "foo called with arg #{arg}" end end m = Foo.new.method(:foo) # => #<Method: Foo#foo> m.receiver # => #<Foo:0x007fb39203eb78> m.receiver.foo(1) # => "foo called with arg 1"
source_location -> [String, Integer] | nil
[permalink][rdoc][edit]-
ソースコードのファイル名と行番号を配列で返します。
その手続オブジェクトが ruby で定義されていない(つまりネイティブである)場合は nil を返します。
[SEE_ALSO] Proc#source_location
# ------- /tmp/foo.rb --------- class Foo def foo; end end # ----- end of /tmp/foo.rb ---- require '/tmp/foo' m = Foo.new.method(:foo) # => #<Method: Foo#foo> m.source_location # => ["/tmp/foo.rb", 2] method(:puts).source_location # => nil
super_method -> Method | nil
[permalink][rdoc][edit]-
self 内で super を実行した際に実行されるメソッドを Method オブジェクトにして返します。
[SEE_ALSO] UnboundMethod#super_method
class Super def foo "superclass method" end end class Sub < Super def foo "subclass method" end end m = Sub.new.method(:foo) # => #<Method: Sub#foo> m.call # => "subclass method" m.super_method # => #<Method: Super#foo> m.super_method.call # => "superclass method"
to_proc -> Proc
[permalink][rdoc][edit]-
self を call する Proc オブジェクトを生成して返します。
class Foo def foo "foo" end end m = Foo.new.method(:foo) # => #<Method: Foo#foo> pr = m.to_proc # => #<Proc:0x007f874d026008 (lambda)> pr.call # => "foo"
unbind -> UnboundMethod
[permalink][rdoc][edit]-
self のレシーバとの関連を取り除いた UnboundMethod オブジェクトを生成して返します。
class Foo def foo "foo" end end m = Foo.new.method(:foo) # => #<Method: Foo#foo> unbound_method = m.unbind # => #<UnboundMethod: Foo#foo> unbound_method.bind(Foo.new) # => #<Method: Foo#foo>