A method invocation expression has four parts:
An arbitrary expression whose value is the object on which the method is invoked. This expression is followed by
.
or::
to separate it from the method name that follows. The expression and separator are optional; if omitted, the method is invoked onself
.The name of the method being invoked. This is the only required piece of a method invocation expression.
The argument values being passed to the method. The list of arguments may be enclosed in parentheses, but these are usually optional. (Optional and required parentheses are discussed in detail in Methods and Parentheses.) If there is more than one argument, they are separated from each other with commas. The number and type of arguments required depend on the method definition. Some methods expect no arguments.
An optional block of code delimited by curly braces or by a
do/end
pair. The method may invoke this code using theyield
keyword. This ability to associate arbitrary code with any method invocation is the basis for Ruby’s powerful iterator methods. We’ll learn much more about blocks associated with method invocations in Iterators and Enumerable Objects and Blocks.
A method name is usually separated from the object on which it is
invoked with a .
. ::
is also allowed, but it is rarely used
because it can make method invocations look more like constant reference
expressions.
When the Ruby interpreter has the name of a method and an object on which it is to be invoked, it finds the appropriate definition of that named method using a process known as “method lookup” or “method name resolution.” The details are not important here, but they are explained thoroughly in Method Lookup.
The value of a method invocation expression is the value of the last evaluated expression in the body of the method. We’ll have more to say about method definitions, method invocations, and method return values in Chapter 6. Here, however, are some examples of method invocations:
puts "hello world" # "puts" invoked on self, with one string arg Math.sqrt(2) # "sqrt" invoked on object Math with one arg message.length # "length" invoked on object message; no args a.each {|x| p x } # "each" invoked on object a, with an associated block
One of the method invocation examples shown earlier was message.length
. You may be tempted to think of
it as a variable reference expression, evaluating to the value of the
variable length
in the object
message
. This is not the case,
however. Ruby has a very pure object-oriented programming model: Ruby
objects may encapsulate any number of internal instance variables, but
they expose only methods to the outside world. Because the length
method expects no arguments and is
invoked without optional parentheses, it looks like a variable
reference. In fact, this is intentional. Methods like these are called
attribute accessor methods, and we say that the message
object has a length
attribute.[4] As we’ll see, it is possible for the message
object to define a method named
length=
. If this method expects a
single argument, then it is an attribute setter method and Ruby invokes
it in response to assignment. If such a method is defined, then these
two lines of code would both invoke the same method:
message.length=(3) # Traditional method invocation message.length = 3 # Method invocation masquerading as assignment
Now consider the following line of code, assuming that the
variable a
holds an array:
a[0]
You might again think that this is a special kind of variable reference expression, where the variable in question is actually an array element. Again, however, this is method invocation. The Ruby interpreter converts the array access into this:
a.[](0)
The array access becomes an invocation of the method named
[]
on the array, with the array index
as its argument. This array access syntax is not limited to arrays. Any
object is allowed to define a method named []
. When the object is “indexed” with square
brackets, any values within the brackets will be passed to the method.
If the []
method is written to expect
three arguments, then you should put three comma-separated expressions within the square
brackets.
Assignment to arrays is also done via method invocation. If the
object o
defines a method named []=
, then the expression o[x]=y
becomes o.[]=(x,y)
, and the expression o[x,y]=z
becomes o.[]=(x,y,z)
.
We’ll see later in this chapter that many of Ruby’s operators are
defined as methods, and expressions like x+y
are evaluated as x.+(y)
, where the method name is +
. The fact that many of Ruby’s operators are
defined as methods means that you can redefine these operators in your
own classes.
Now let’s consider this very simple expression:
x
If a variable named x
exists
(that is, if the Ruby interpreter has seen an assignment to x
), then this is a variable reference
expression. If no such variable exists, then this is an invocation of
the method x
, with no arguments, on
self
.
The Ruby-reserved word super
is
a special kind of method invocation expression. This keyword is used
when creating a subclass of another class. By itself, super
passes the arguments of the current
method to the method with the same name in the superclass. It can also
be used as if it were actually the name of a method and can be followed
by an arbitrary argument list. The super
keyword is covered in detail in Augmenting Behavior by Chaining.
[4] This is not to say that every no-argument method is an
attribute accessor. The sort
method of an array, for example, has no arguments, but it cannot be
said to return an attribute value.
Get The Ruby Programming Language now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.