Classes in Ruby—and other languages—are a way of organizing objects into mini code-factories: where the class itself is a template that gets filled out for each copy, or instance, of itself. A great real-world explanation of classes is in role-playing games where at the beginning you create your own character (and credit for this thought goes to the Invent With Python blogger). Your character will belong to a class—it'll be a Warrior, or a Druid, or a Healer, etc—but it will be unique to you, because it will have a name that you give it, and other information like special clothes that it wears because you decided on them, etc. Based on its class, your character will also have its own behaviours: it will be able to heal other characters if it's a Healer, or talk to plants if it's a Druid, or kick some serious butt if it's a Warrior, etc, and for the most part, these special behaviours will not be available to characters from other classes.
Similarly, a Ruby class has state—attributes like name, etc—and behaviours—methods that instances of itself can execute. We can think of attributes as things that describe the object and give it an identity from other instances of that class: it'll have its own name, for example. So attributes are things that that instance of the class IS, and its methods are things that it DOES.
When a copy of the class is taken to create a new instance of that class, it is given its own state/attributes. To illustrate, here's a Book class:
Books in the real world aren't meant to DO anything on their own (not that that stops them from being powerful forces...), but they are certainly meant to have unique attributes: their own title and author, for example. In the example above, the class Book is a set of code that, when a copy of itself is made and given a title and an author, will be a unique Book object.
author expose the values
contained inside the instance variables
@author respectively. (Instance
variables are variables that are expressely there to hold values for a specific instance of that class: they are
available anywhere inside the class to give their value or to have that value altered.) Using
we can abstract away those simple
author methods into the following:
attr_reader :title, :author, which under the hood is exactly what those little methods are, just
differently written. Here's the Book class updated to use
Looks like the parts inside
initialize changed too! Like
writing variable assignments like this is just a shorter, one-line way of doing the same thing as before.
Now let's make a Library class:
Our Library class is a little more complex than our Book class. Our Library class has methods that allow it to
DO stuff, not just BE stuff: it can
add_book into itself, it can
suggest_a_book to the
user, and it can
suggest_an_author too. Don't focus too much on the code inside
just yet, we'll get to it in a moment. Right now, let's make a new Library object, and ask it to show itself to us
That's a very interesting bit of code right there in the comments: when we asked
to show itself to us, it printed out that long string of characters. The first part is clear: it's telling us
what class it belongs to. The next bit of numbers is its object ID; and that last part, the
@books=, is its
books, which we said is empty when we first initialize our Library. (Since
all libraries start out empty at first and get filled up with books over time.) So now, let's add some books
to our library using the
So before, our library had an empty array for
@books attribute: but now it's filled with 4 Book objects, each
with their own attributes of
@author! This is because the Library method
takes two arguments, title and author, and uses those arguments to create a new Book object each time it is called;
then it "shovels" the new Book object as a whole—including its object ID and everything else about it, like its
It's a bit hard to read those long indecipherable object strings. Let's ask it to show us its books in a nicer way:
That's much nicer!
@books holds the value of an array of objects, and the array method
allows us to iterate over
@books and ask each book object to put itself to the console in the way we've
Now let's try out its rather pushy
Super nifty! That's all for today, I'm feeling like opening up my copy of The Well Grounded Rubyist now.