Skip to content

MR07 Creating a Class

Dave Strus edited this page Jan 31, 2016 · 2 revisions

Creating a Class

In this unit, we'll do the following:

  • Extract the current functionality into a class

We'll learn about the following concepts or tools:

  • Classes
  • Instances
  • Instance methods

Where to start?

Right now, everything is happening within main, which is an instance of Object, the class of which every other class is a descendent.

We can start our reorganization by making everything happen within a class of our own making. This class would represent our entire application. Let's call it RosterApplication.

Classes are constants, and like all constants their names must begin with a capital letter. It is conventional to use camel case for the remainder of the name, e.g. MyMultiwordClassName.

Let's define our new class at the beginning of our script.

#!/usr/bin/env ruby
require 'pry'

class RosterApplication
end

For now, let's just put all our functionality in a single instance method called start.

A class's instance methods can be called from objects that are instances of the class (created by ClassName.new), but not from the class itself.

class RosterApplication
  def start
    puts 'Hello, mutant collector!'

    print 'Real name: '
    real_name = gets.chomp
    print 'Mutant name: '
    mutant_name = gets.chomp
    print 'Power: '
    power = gets.chomp
    puts "#{mutant_name} (also known as #{real_name}) has an incredible power: #{power}."
  end
end

If we run it now, nothing will appear to happen. We're defining our class, but never doing anything with it. We need to create an instance of RosterApplication, and call start on that instance.

Add this to the end of the script:

app = RosterApplication.new
app.start

Now it behaves exactly as it did before:

$ ./roster.rb
Hello, mutant collector!
Real name: Emanuel
Mutant name: Xondar
Power: Invulnerability
Xondar (also known as Emanuel) has an incredible power: Invulnerability.

Why bother?

So how have we actually benefited from this exercise?

We've given our app a tiny bit of structure. Right now, it's so simple that it hardly seems worth it. But as it grows in complexity, encapsulating behavior in a well-designed class will help to keep our code readable and testable.

Without adding any new behavior, there are still things we can do to improve our code's organization. The only way to tell what this app does is to read every line of code. If we extract some of the behavior into separate methods, we can give those methods names that give some insight into what they accomplish.

Let's start by extracting our prompts and variable assignments into a new method called collect_mutant_data.

class RosterApplication
  def start
    puts 'Hello, mutant collector!'
  end

  def collect_mutant_data
    print 'Real name: '
    real_name = gets.chomp
    print 'Mutant name: '
    mutant_name = gets.chomp
    print 'Power: '
    power = gets.chomp
    puts "#{mutant_name} (also known as #{real_name}) has an incredible power: #{power}."
  end
end

If we always want to run collect_mutant_data when an instance of our application starts, we could call it from the start method.

def start
  puts 'Hello, mutant collector!'
  collect_mutant_data
end

I prefer to leave it up to developers to call that manually, for maximum flexibility. Let's call it manually from our new instance.

#!/usr/bin/env ruby
require 'pry'

class RosterApplication
  def start
    puts 'Hello, mutant collector!'
  end

  def collect_mutant_data
    print 'Real name: '
    real_name = gets.chomp
    print 'Mutant name: '
    mutant_name = gets.chomp
    print 'Power: '
    power = gets.chomp
    puts "#{mutant_name} (also known as #{real_name}) has an incredible power: #{power}."
  end
end

app = RosterApplication.new
app.start
app.collect_mutant_data

If you were reading this script, and skipped over the class definition, you could still get an idea of what it's doing, simply by reading these three lines of code:

app = RosterApplication.new
app.start
app.collect_mutant_data

It starts the application and gets some mutant data. We don't know exactly how it does that; we just know that it does.

Want to get the data for three mutants? No problem!

app = RosterApplication.new
app.start

3.times do
  app.collect_mutant_data
end