Classes

Examining how to package up objects and methods into classes for better organization and increased functionality.

Scroll down...

Content

Resources

Comments

Classes are essential to an object-oriented approach. They are like blueprints -- you specify how an object should look and act so you can make as many copies as you need to later. They allow you to DRY up your code by putting the methods used by these objects in one central location. They also help you encapsulate your data better and organize your code more coherently.

More generally, classes are the blueprint for producing objects like Dogs or Vikings or blog Posts. Each object has behavior and state . The class defines what behavior is available to each object via methods and keeps track of that object's state using instance variables.

Classes are incredibly powerful. To get you familiar with them, we'll start by looking at some pretty literal examples like the objects referenced above. Many of the things you model in web programming will resemble this fairly literal set of objects but many more will actually be a bit more abstract. For instance, in Rails there is a Router class which packages up all the functionality to send incoming HTTP requests into the right area of your application. Our ultimate goal is for you to be able to deploy classes to solve these more abstract use cases.

In this lesson, though, we'll start with the basics of classes. Over the next several lessons, we'll show you how instance variables, instance methods, class variables and class methods are used to flesh out the state and functionality of your class (and its instances).

Our goal for the next several lessons is that you become quite familiar with the idea of classes and the particulars of their use. We'll cover how classes are defined, how instances of these classes are instantiated, and how to give them necessary functionality with methods and variables.

When to Use a Class

There are generally three good indications that you should package up your functionality into a class instead of individual methods or objects:

  1. Your objects start needing functionality of their own (e.g. methods).
  2. Multiple objects need access to the same general behavior.
  3. You want multiple copies of the same object to each have their own individual attributes and state (instance variables).

As you get deeper into OOP, the rule of thumb becomes more like "just make a class for it".

From Hashes to Classes

You can go a long way by using the basic data structures Ruby gives you like arrays and hashes. Let's say you're building a game and the player needs a bunch of attributes stored. A hash seems like a pretty reasonable way to do this:

> player1 = {:health => 100, :name => "Oleg", :attack_damage => 12}
#=> {:health => 100, :name => "Oleg", :attack_damage => 12}

You might assume that the game script handles all the possible interactions between your player and any other game objects. That should already be a warning sign that you might have a "god" script that does too much...

But what if you want to bring your player to life and actually give it functionality of its own like walking or healing or attacking? It's best to bring the hash to life by making it a class and including any desired functionality as instance methods.

We'll dive into the details of this below, but a simple version of your class might look like:

class Viking
    def initialize(name)
        @name = name
        @health = 100
        @attack_damage = 12
    end
    def attack(victim)
        #... code to attack ...
    end
end

# IRB
> player1 = Viking.new("Oleg")
#=> #<Viking:0x007fc20d855ad0 @health=100, @name="Oleg", @attack_damage=12> 

This allows your player to attack other players and gives you the added benefits of being able to create a new player by simply specifying the name. This will come in handy if you're building an army with 1000 Vikings.

In a more general sense, when you just store your Viking's name, age, health, and strength in a hash, it just kind of sits there. When you want to make an army of Vikings who can do stuff like eat, travel, sleep and, of course, attack, you need to make it a class of its own.

Think of a class as a container for methods and variables that you'll want each object to have access to:

class Viking
    # put your methods and variables here!
end

So, in this case, the big reasons for us using a class is because we wanted our object to actually do things and we wanted to be able to make lots of them.

Naming Classes

The class name is always capitalized and, for multiple words, uses CamelCase (capitalized with no spaces) not the snake_case (lowercase with spaces as underscores) you've typically seen for variables and methods. The name should be the singular "thing" you'll be building.

# WRONG -- plural
class VikingWarriors

# WRONG -- snake case
class Viking_Warrior

# WRONG -- lowercase
class vikingwarrior

# RIGHT
class VikingWarrior

Instantiating Class Instances

To be able to amass a horde of 1000 Vikings, you need a way to create new ones. Each time you do that, it's called Instantiating a new Viking. You use a special new method to do that.

This isn't anything new -- you've done it many times over for the Array class already:

> my_arr = Array.new
#=> []

new is a Class Method, which means that you call it on the class (in this case Array) and not the specific instance of that class (which would be my_arr here). We'll talk about these in detail a bit later on.

When you call that method, it creates a new instance (object) of that class and then runs a special method inside the class called initialize, which will set up that class to be ready for use. If you pass variables to your class when you create it with the new method, they will be available to the initialize method.

Your Viking class would start by looking like:

class Viking
    def initialize(name, age, health, strength)
        # set up your new viking however you want to
    end
end

Running the initialize method upon instantiating a new object automatically occurs and it's a very common programming pattern that Ruby is just borrowing.

Code Review

The important bits of code from this lesson

# Instantiate a class
oleg = Viking.new("Oleg", 100, 19, 8)

Wrapping Up

This was probably mostly a refresher for you but at least we're all on the same page now. We'll dig deeper into the workings of classes over the next several lessons when we cover instance variables/methods and class variables/methods.



Sign up to track your progress for free

There are ( ) additional resources for this lesson. Check them out!

There are no additional resources for this lesson just yet!

Sorry, comments aren't active just yet!

Next Lesson: Instance Variables and Methods