您可以使用obj.method(:method_name)将方法变为方法对象.而Method正是这些方法对象的类.它封装了方法的实体(而不是方法名)和被调对象(receiver).与Proc不同的是,它不能保持context.
它与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 ... ) { ... }启动被封装在方法对象中的方法. 参数和块将被原封不动地传递给方法.
为了与普通方法调用取得某种形式上的一致,Ruby特地准备了self[]这种调用形式. 但是它和Array#[ ]这样的[ ]方法之间并没有意义上的关联.
若方法对象已受污染,就以4级安全级别来执行该方法(请参考与安全级别有关的其他详细信息).
arity返回方法对象的参数的个数. 若self的参数个数不定,则返回
-(最底限个数 + 1)
信息.
inspect请参考Object#inspect. 它返回下列形式的字符串.
#<Method: klass1(klass2)#method> (形式1)
在Method#inspect中,Klass1是被调(receiver)的类名.在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 特性: 若klass1与klass2相同时,则为下列形式.
#<Method: klass1#method> (形式2)
ruby 1.7 特性:若是特殊方法,
#<Method: obj.method> (形式3) #<Method: klass1(klass2).method> (形式4)
则返回上述形式的字符串.在第2种形式中,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生成并返回一个调用(call)self的Proc对象.
unbind摘除self同被调(receiver)间的关联之后,返回一个UnboundMethod对象.