Methods in Ruby: objects or not?
You can't really tell.
The only way to get access to a method is to send the #method
message to some object, which will then return a Method
object. But is that Method
object the method itself? Or is it a wrapper around the method? Or is it a converted version of the original method?
You can't know: if you want to look at a method, you have to call #method
, at which point you definitely will get an object. What it was before you called #method
you can't look at, therefore you can't tell.
A couple of datapoints: in Ruby, everything returns a value. What does def
return? It always returns nil
, not a Method
object. And define_method
? It returns a Proc
, but not a Method
(nor an UnboundMethod
). [Note: in Rubinius, def
returns the compiled bytecode of the method, but still not a Method
object.]
If you look at the 4th and 5th paragraphs of Section 6.1 of the Ruby Language Specification (lines 29-34 and 1-5 on pages 5 and 6), you can clearly see that there is a distinction drawn between methods and objects. And if you look at the specification of the builtin classes, you will find that neither Method
nor UnboundMethod
are in there, nor is Object#method
. IOW: you can build a perfectly standards-compliant Ruby interpreter in which methods aren't objects.
Now, blocks OTOH definitely aren't objects. There are many ways to construct Proc
objects from blocks, which then have the same behavior as the original block (lambda
, proc
, Proc.new
, the &
sigil), but blocks themselves aren't objects.
Think about it this way: you can pass a string to File.new
to construct a file object, but that doesn't make a string a file. You can pass a block to Proc.new
to construct a proc object, but that doesn't make a block a proc.
Methods are a fundamental part of Ruby's syntax, but they are not values that Ruby programs can operate on. That is, Ruby's methods are not objects in the way that strings, numbers, and arrays are. It is possible, however, to obtain a Method object that represents a given method, and we can invoke methods indirectly through Method objects.
From The Ruby Programming Language: