Chapter 3: Truly Ruby A Journey at its End


At last you have arrived! Gaze back at how far you have come! You've learn nearly all the syntax one would require to start making truly enlightened Ruby programs.

We've gone on and on about how Ruby is an object-oriented programming language. Pretty much everything in Ruby is an object as you know. Objects have methods and attributes or properties. Objects are simply concrete instances of an abstract category, or class.

'underpants'.length


Here 'underpants' is a string object that has a method .length, and a length attribute (number of characters) of 10. We'll see that you can build complex objects with methods to make them more useful in your programs. But first we need to learn how to create objects at will.

A class is means to create many distinct objects with similar attributes and methods. Classes are similar to types or kinds in that they contain descriptions of what all instances of that class have in common. It lists out what it takes to be that kind of object. Here is the class syntax:

class MyClass
  #Methods and Attributes
end


This syntax is very similar to how we define methods. The class keyword is like the def keyword. The names of classes are always written in upper CamelCase and don't use underscores. Here we create an instance of MyClass:

my_instance = MyClass.new


We create a variable called my_instance and set it equal to a new object created by running the .new method on the MyClass class. Now when we use my_instance in our programs, we will have all of the methods and attributes in MyClass available to us. This is a very DRY way to write programs, as there is no need to rewrite methods or define values for each distinct object used. Classes declarations often include specify arguments that will be needed to create a new class object:

class PowerRanger
  def initialize(animal, color)
    @animal = animal
    @color = color
  end
end


In this example we are adding a method into our class PowerRanger. We define initialize as a method that takes two arguments, one representing the ranger's power animal, and another representing the color of their suit. Inside the method we create two special variables @animal and @color called instance variables. These are variables that attach to the instance of a class when it is created. All instance variables begin with @ to differentiate them from regular variables. Above we set these variables so that any time we create a new PowerRanger object, they will have an animal and a color created using animal and color passed to it.

kimberly = PowerRanger.new('Pterodactyl', 'pink')


We create kimberly, a new 'pink' (the @color attribute) PowerRanger who draws her power from the 'Pterodactyl' (the @animal attribute). Those variables are attached to kimberly in particular. They are HERS.

We frequently have to concern ourselves with the scope of variables and methods. The scope is how reachable variables and methods are to different parts of your programs. Some are available to all parts of the program, some are only to members of specified classes, and others are only to class objects.

class Car
  @@cars_sold = 0
  def initialize(make, model)
    @make = make
    @model = model
    @@cars_sold += 1
  end
end


Class variables belong to the class itsel instead of to an instance. Class variables start with the @@. Above we create the @@cars_sold variable for Car class to keep track of the number of cars we sell (or Car objects we create). Notice how the variable is outside of the initialize code block. This is a great way to visualize scope. In the above example, there is just one copy of the @@cars_sold variable shared by all Car objects, and it increases every time a new instance is created.

We also want to have variables available to all parts of our Ruby programs. We do this using global variables. We create global variables using $, and they can be placed inside or outside of classes or methods. Take a look at our new class declaration:

class Car
  $manufacturer = 'Toyota'
  @@cars_sold = 0
  def initialize(model, year)
    @model = model
    @year = year
    @@cars_sold += 1
  end
end


Here we see that every new Car object we create will have the variable $manufacturer. Because it is global, we can also access that variable at any time from anywhere in the program.