Object-Oriented Programming


What Is Object-Oriented Programming?

You don’t need OOP (Object Oriented Programming) to write code.

You could write any Ruby program without OOP.

But using OOP makes things easier if you’re writing a non-trivial program.

Why?

Because OOP is all about how you design & organize your code.

You create classes that represent concepts in your program.

And each class is responsible for doing something.

For example, you may have a user class that knows the username & email address.

Or a Store class that knows how to manage its own inventory.

How to Create a Ruby Class

To create a class you’ll need the class keyword.

Here’s a Book class:

class Book
end

This class does nothing, but you can create objects from it.

An object is an individual product of the class.

The class is the blueprint & the objects are the products.

Every object is different from each other.

Why?

Because this allows you to create many objects that are the same thing (like a Book) but have different data (title, author, etc.)

How to Create Ruby Objects

If you have a class you can create objects from it.

Here’s how:

book = Book.new

Notice the new method we are calling on Book.

That’s how you create a Book object.

You could also do this with Ruby built-in classes.

Like Array:

array = Array.new

But since these are built into Ruby we get special syntax to create them.

Example:

array = []
hash  = {}
string = ""

For your own classes you have to use new to create objects.

Ruby Methods – How Classes Learn To Do Things

Let’s make our Book class smarter & teach it how to do something.

You do this by writing methods.

A method is a command that you can reuse multiple times & it’s associated with a specific class.

It’s like variables but for code instead of data.

Here’s an example:

class Book
  def what_am_i
    puts "I'm a book!"
  end
end

I’ve created a method named what_am_i.

When you call this method by its name it will print some text.

This is how you call a method:

book = Book.new

book.what_am_i

Important!

You call the method on an object of Book, not on Book itself.

These are “instance methods”.

Another name for an object is “instance of a class”.

Storing Data With Instance Variables

Objects can hold their own data.

Here’s how:

class Book
  def initialize(title, author)
    @title  = title
    @author = author
  end
end

There are a few things going on here:

First, we have this initialize method.

This is a special Ruby method that is called when you create an object.

Then we have these @something variables.

What are those?

Instance variables.

Why do we need them?

To store data that all the methods (in the same class) can use.

Without instance variables these variables wouldn’t exist outside the initialize method.

Attribute Accessors

The last piece of the puzzle is how to access this data we prepared inside initialize.

There are two ways:

  1. If you’re inside an instance method you can reference it directly (@variable_name)
  2. If you’re outside the class you’ll need an attribute accessor

Let’s say we create two books:

deep_dive = Book.new("Ruby Deep Dive", "Jesus Castello")
boba = Book.new("BOBA", "Grant Cardone")

If I want to access the title:

deep_dive.title

I’m going to get this error:

NoMethodError: undefined method 'title'

Instance variables are private by default, that’s why we can’t get the title directly.

If you want access you have to be explicit about it.

You can do that using attribute accessors.

Like this:

class Book
  attr_reader :title, :author

  def initialize(title, author)
    @title  = title
    @author = author
  end
end

This attr_reader is like opening a window so people can peer into the object & get the data they want.

Now if I do:

deep_dive.author

# "Jesus Castello"

It works!

There is nothing special about this, an attr_reader is a shortcut for writing an accessor method like this one:

def author
  @author
end

Because methods have access to instance variables they can return their value.

There are other kinds of attribute accessors:

  • attr_reader (read-only)
  • attr_writer (write-only)
  • attr_accessor (read & write)

When you use attr_writer or attr_accessor you can change the value of instance variables outside the class.

Example:

deep_dive.title = "Ruby"

As a general rule you want to minimize outside access to instance variables, if you only need reading use attr_reader, not attr_accessor.

What is a Class Method?

Everything you have seen so far is about instances, objects created from the class (using new).

But it’s also possible to create class-level methods.

Like this:

class Food
  def self.cook
  end
end

The self part before the method name makes this a class method.

The self in this context refers to the class name (Food).

Now:

The difference between an instance method & a class method is that instance methods are for objects.

And class methods are for the class itself.

How to Use Class Methods

You call them like this:

Food.cook

Why would you want to create a class method?

Well, you don’t have to.

Most of the time you’ll be working with instance methods.

But sometimes it doesn’t make sense to create an object.

Like when using the Math class in Ruby…

…this gives you the square root of 25:

Math.sqrt(25)

You don’t need a Math object because Math doesn’t store any data.

The methods in Math take one value & give you an answer.

That’s the use-case for class methods.

Practice Time!

I want you to practice what you learned.

That’s the only way you’ll develop this skill & improve your understanding!

Try this:

  • Create a Cat class
  • Add a meow method to the Cat class that prints "I'm a cat, gimme food & pet me now!"
  • Create a cat object & call the meow method 3 times

Copyright RubyGuides.com