Ruby’s methods and blocks are executable language constructs,
but they are not objects. Procs and lambdas are object versions of
blocks; they can be executed and also manipulated as data. Ruby has
powerful metaprogramming (or reflection)
capabilities, and methods can actually be represented as instances of
the Method
class. (Metaprogramming is
covered in Chapter 8, but Method
objects are introduced here.) You
should note that invoking a method through a Method
object is less efficient than invoking
it directly. Method
objects are not
typically used as often as lambdas and procs.
The Object
class defines a
method named method
. Pass it a method
name, as a string or a symbol, and it returns a Method
object representing the named method of
the receiver (or throws a NameError
if there is no such method). For example:
m = 0.method(:succ) # A Method representing the succ method of Fixnum 0
In Ruby 1.9, you can also use public_method
to obtain a Method
object. It works like method
does but
ignores protected and private methods (see Method Visibility: Public, Protected, Private).
The Method
class is not a
subclass of Proc
, but it behaves much
like it. Method
objects are invoked
with the call
method (or the []
operator), just as Proc
objects are. And Method
defines an arity
method just like the arity
method of Proc
. To invoke the Method
m
:
puts m.call # Same as puts 0.succ. Or use puts m[].
Invoking a method through a Method
object does not change the invocation
semantics, nor does it alter the meaning of control-flow statements such
as return
and break
. The call
method of a Method
object uses method-invocation
semantics, not yield semantics. Method
objects, therefore, behave more like
lambdas than like procs.
Method
objects work very much
like Proc
objects and can usually be
used in place of them. When a true Proc
is required, you can use Method.to_proc
to convert a Method
to a Proc
. This is why Method
objects can be prefixed with an
ampersand and passed to a method in place of a block. For
example:
def square(x); x*x; end puts (1..10).map(&method(:square))
One important difference between Method
objects and Proc
objects is that Method
objects are not closures. Ruby’s
methods are intended to be completely self-contained, and they never
have access to local variables outside of their own scope. The only
binding retained by a Method
object,
therefore, is the value of self
—the
object on which the method is to be invoked.
In Ruby 1.9, the Method
class
defines three methods that are not available in 1.8: name
returns the name of the method as a
string; owner
returns the class in
which the method was defined; and receiver
returns the object to which the
method is bound. For any method object m
, m.receiver.class
must be equal to or a
subclass of m.owner
.
In addition to the Method
class,
Ruby also defines an UnboundMethod
class. As its name suggests, an UnboundMethod
object represents a method,
without a binding to the object on which it is to be invoked. Because
an UnboundMethod
is unbound, it
cannot be invoked, and the
UnboundMethod
class does not define
a call
or []
method.
To obtain an UnboundMethod
object, use the instance_method
method of any class or module:
unbound_plus = Fixnum.instance_method("+")
In Ruby 1.9, you can also use public_instance_method
to obtain an UnboundMethod
object. It works like instance_method
does, but it ignores
protected and private methods (see Method Visibility: Public, Protected, Private).
In order to invoke an unbound method, you must first bind it to
an object using the bind
method:
plus_2 = unbound_plus.bind(2) # Bind the method to the object 2
The bind
method returns a Method
object, which can be invoked with its call
method:
sum = plus_2.call(2) # => 4
Another way to obtain an UnboundMethod
object is with the unbind
method of the Method
class:
plus_3 = plus_2.unbind.bind(3)
In Ruby 1.9, UnboundMethod
has name
and owner
methods that work just as they do for
the Method
class.
18.118.139.224