Using Objects
8.1 Introduction
In Chapter 6, we discussed the concept of arrays and hashes, additional structures that can be used to store data. In this and the following two chapters, we discuss objects.
8.2 Objects and Built-in Objects
So far, we have been writing code that is procedural in nature; that is, code whose logical flow starts at the top and works its way to the bottom. Any computer program can be written in a procedural manner. However, when code gets long, it becomes difficult to debug and maintain. It also becomes redundant and dangerous to write the same code over and over. The object-oriented approach was created for dealing with these very issues. To switch to objects, you must understand why they are useful in the first place.
Imagine a product as complex as Microsoft Word. To produce it, a team of Microsoft programmers had to write millions of lines of code, with hundreds of people working on the code at the same time. To support simultaneous development, the code was segmented by functionality. Understanding how such complex products get subdivided into manageable pieces requires that we first understand the building blocks of such code. These building blocks in Ruby are classes that define objects.
8.2.1 Objects
Objects and object-oriented programming simplify the implementation of large programs. If you work on a program by yourself, it is up to you to organize your work. If you work with 100 other programmers, then everything must be nicely compartmentalized; otherwise, each programmer will constantly step on the other programmers’ toes. There is nothing worse than getting your piece of a program to work and finding out that you inadvertently broke someone else’s.
Gem of Wisdom
Ruby is a truly object-oriented language, and that is one reason
we picked it for this book. Objects usually correspond to entities
that exist in the real world. They encapsulate values and support
actions as well. While a variable might have a value 5, an object
named airplane
might have one value
of Boeing 747
and another value of
current location
. Also, airplane
can have an action that says
fly()
that might change its current
location based on how far it has flown.
If you and your friend decide to work on a project together, you
can easily run into trouble. Imagine if your friend makes a variable
called x
and manipulates it. You
remain unaware of this changing of value. So later on in the code, you
likewise decide to use a variable called x
. Your piece of code and your friend’s piece
of code both work on their own, but when you integrate them, strange
problems occur.
Objects are designed to separate key activities in a program so
that once you get something to work, you need not constantly worry about
accidentally breaking it when you make new objects. The activities are
essentially isolated from one another. They can communicate information
without the need to know how it is produced and what the specifics of
the implementation are. For example, a programmer might build an object
called TicTacToe
when making a
tic-tac-toe board game. Once the part of the program that draws the
board works, everyone can just communicate with that object in a way
that ensures that no one steps on another programmer’s toes.
Objects enable programs to be compartmentalized so that programmers can work at the same time without fear of running over one another. Consider a construction crew building a house. Someone painting one room does not constantly check on the work of someone who is painting another room. This is because the rooms are compartmentalized—they have walls and ceilings that keep paint from dripping from one room to the other. However, two painters working in the same room must always be in constant communication to be effective and efficient. For example, if they were not communicating, it would be possible that one painter could drip paint on the other or paint the worker into a corner.
Objects are isolated pieces of code that have their own private chunks of data and private actions that can be performed with that data. The actions that an object may perform are referred to as methods. Object-oriented programming tries to create the most logical separation between pieces of code.
8.2.2 Built-in Objects
Without realizing it, you have been using objects since the moment you began to program anything in Ruby. In Chapter 3, you began using objects when you started using variables; you just did not have to think about it. In fact, everything in Ruby is an object, and this section will discuss some of the more common objects you will use.
An application programming interface, or API, is an interface provided to the programmer to allow the use of certain functionality without knowing the specifics of the implementation. When you downloaded the Ruby interpreter to your hard drive, you probably downloaded a copy of Ruby’s API documentation with it, but in case you did not, it is available online. If you visit this site, you will notice it has three headings: files, classes, and methods. For now, we will focus on classes.
A class defines the characteristics and behaviors of an object. It contains the variables and the code necessary to implement the operations of the object, usually called methods. If you look through the list of classes, you will see there are many. However, you have already used a few of them. Some classes you may have already used are the array, Fixnum, float, and string classes. While there are many more classes than these, it is not required that you know what they do or what they consist of. However, it is required that you know how to use them when the time comes.
For any class, all the supported methods for the class are provided.
For example, the string class (see Figures Figure 8-1
and Figure 8-2) has a length method, str.length => integer
. This means that if
we call the string’s length method, it will return an integer. The next
part is simply a description of the method, and it does what one would
expect a length method to do. The following is an example of using this
method:
irb
(
main
):
001
:
0
>
"hello"
.
length
=>
5
Simply put, we call the string class method length on the string object “hello,” and we get back the number of characters in “hello,” which is 5. This is a simple example of calling, or using, a method. However, calling a method is not always this simple. Let’s look at another example of a method from the string class.


The example method in Figure 8-3 is significantly more
difficult. It shows multiple ways to call the method index
, along with the results returned when
the method is called. By looking at the description of the method taken
from the actual Ruby documentation website and written on top of the
example calls, you may be able to decipher how calling this method
works, but it uses concepts we have not yet discussed. The main concept
here is that this method needs some type of outside data to work;
supplying this outside data to a method while calling it is known as
parameter passing.

8.2.3 Parameter Passing
Looking at the list of built-in methods, you will see that the
syntax for some of them requires a variable in parentheses; these
variables are called parameters. When using
built-in methods with parameters, you are sending the value of the
variable to the method to be manipulated. Consider the imaginary method
called multiplier
in Example 8-1.
Parameter passing
1
x
=
3
2
y
=
x
.
multiplier
(
4
)
3
puts
"The number is: "
+
y
.
to_s
Line 1 defines the variable x
to be 3. The next line assigns a value to y
by calling our imaginary method multiplier
and passing the value of 4 as a
parameter. If we looked at the output of this method, it would
show:
The
number
is
:
12
By looking at this, you can assume that the method multiplies the
value of the parameter by a certain value. If we want to find out what
the multiplier
method really does, we
can change the value of the parameter to 5. After doing this, the
observed output is:
The
number
is
:
15
You can now conclude that the multiplier
method multiplies the value of the
parameter by the value of x
. The key
concept of parameters in methods is that it does not matter what value
is being passed; an output is generated using the same operations within
the method every time. Think of the method as a black box, as depicted
in Figure 8-4.

The system has an input z
, an
output y
, and a black box. The input
z
is sent to the black box, which
manipulates the variable and then outputs it as y
. We do not know, nor do we care, what
happens inside the black box. The only thing that matters is the
resultant output.
Now let’s look at an example using the actual Ruby built-in method
called split
. This method is used
with strings and splits the strings into array elements based on the
parameter passed. In this case, this will be the delimiter. Observe the
example in Example 8-2.
Split example 1
1
my_string
=
"Good;day;sir!"
2
arr
=
my_string
.
split
(
";"
)
3
puts
arr
4
5
# The following array is created:
6
# arr[0]: "Good"
7
# arr[1]: "day"
8
# arr[2]: "sir!"
Line 1 defines a string object with the value “Good;day;sir!”
Line 2 calls the built-in method
split
with a semicolon as the parameter.Line 3 outputs the values of
my_array
.
After executing the code, the array shown in lines 6–8 will be created, and the output will be the following:
$
ruby
split_1
.
rb
Good
day
sir!
As you can see, the split
method has created an array with three indices based on the parameter
passed (in this case, the semicolon). Now, what if we changed the
parameter of the split
method to
something else, as shown in Example 8-3?
Split example 2
1
my_string
=
"Good;day;sir!"
2
arr
=
my_string
.
split
(
"a"
)
3
puts
arr
4
5
# The following array is created:
6
# arr[0]: "Good;d"
7
# arr[1]: "y;sir!"
Now the split
method will
perform the same operation, but instead of splitting the string object
based on the semicolon, it will split the string into array values based
on the new parameter. The resultant array is once again shown in the
comments in lines 6 and 7, with the following output:
$
ruby
split_2
.
rb
Good
;
d
y
;
sir!
The split
method has created an
array with two elements based on the parameter a
. You can see that no matter what the input
is, the program will always perform the same operation based on the
parameter passed. It does not matter what the input is or what is inside
the method; the split
method will
create arrays splitting your string object wherever there is an
occurrence of the indicated parameter.
An astute reader may wonder what would happen if the chosen
parameter for split
did not exist in
the string, my_string
. In this case,
an array of one element is returned, with the first element containing
my_string
. The code in Example 8-4 illustrates this.
The output follows from the array’s structure, as shown in line 6.
Split example 3
1
my_string
=
"Good;day;sir!"
2
arr
=
my_string
.
split
(
"z"
)
3
puts
arr
4
5
# The following array is created:
6
# arr[0]: "Good;day;sir!"
$
ruby
split_3
.
rb
Good
;
day
;
sir!
8.3 Summary
Objects and their corresponding methods are the building blocks of many of today’s software systems. For all object-oriented programming languages, some objects and methods are predefined, and those are always specified in the language manuals.
In that light, we introduced objects, explained built-in objects, and discussed parameter passing, a mechanism to transfer information in and out of objects.
8.3.1 Key Concepts
Classes define the characteristics and behaviors of objects belonging to the class.
Objects are instantiations of a class. They have a name and possess all the properties of the class, namely, the variables and the methods.
The application user interface, or API, is an interface used to communicate with some underlying functionality.
8.3.2 Key Definitions
Object: An isolated piece of code that has its own actions and data.
Method: The action that an object may perform.
API: An interface provided to the programmer to allow the use of certain functionality without knowing the specifics of the implementation.
Class: Construct that contains the definition of an object template and the implementation of the methods.
Parameter passing: The passing of data to a method within an object.
8.4 Exercises
Provide code using the
split
method to separate the following string into individual words and then display them:my_string
=
"Roses!are!red!Violets!are!blue"
You are programming part of the sign-up procedure for an online computer game. Write a program that prompts the user to enter his or her user ID and password and enforces the following restrictions:
User IDs and passwords must be at least seven characters in length.
Passwords must contain at least one of each of the following: uppercase character, lowercase character, number, and symbol.
Hint: use the documentation for the string class.
Write a program that prompts the user for three words and then outputs the total and average number of characters in the three words.
What would result if you were to type the following into
irb
?irb
(
main
):
001
:
0
>
"12345"
.
length
irb
(
main
):
002
:
0
>
"12345"
*
5
irb
(
main
):
003
:
0
>
"12345"
.
index
(
2
)
irb
(
main
):
004
:
0
>
"12345"
.
index
(
0
)
irb
(
main
):
005
:
0
>
"12345"
.
index
(
1
)
irb
(
main
):
006
:
0
>
"12345"
.
index
(
5
)
What does it mean to pass a parameter to a method? What happens when a parameter is passed to a method?
Write a function multiplier that multiplies the value passed to it by
x
. Have the function ask the user for the value ofx
.