Everything is an object in Ruby, even simple numbers, strings, arrays, the boolean values true and false, etc. Everything, without exception, is an object. This means every object (anything that can be assigned to a variable, more or less anything within a Ruby program) has methods, has a class, and can be treated as any other object. There are no "special" objects as there are in languages such as Java, where the base types (such as numbers) are not really objects, and must be "boxed" to be treated as objects.
Another thing to think about here is pass by value or pass by reference. Ruby is pass by reference, objects are never copied around unless an explicit copy method (such as dup) is called. Ruby has no concept of "value types" vs. "reference types" as in C#, everything is a "reference type."
All that said, not all objects are created equally. Some of the base types in Ruby are implemented in a way to make them faster, but they lose some of their object oriented functionality. For instance, the number 7 is a literal FixNum object. However, only one of this object can exist, any future references to the number 7 also refer to this same object. The same applies for other Numeric object, symbols and a few others. This also implies that they have no instance variables. They do however have classes though, and new methods can be added to those classes like any other. Just be aware that some of the base types in Ruby are objects but may act slightly differently.
Defining Classes and Creating Objects
If you've done any Ruby programming, you've dealt with objects. In the following example, the string literal creates an object of the String type, which is assigned to a variable.
my_string = "My hovercraft is full of eels"
We now have an object that represents our string (which explains the sorry state our hovercraft is in). What is this object? At its core, all objects are the same. They are collections of data (usually in the form of instance variables though a string is "special" and there's a C string underneath) and a reference to a Class object (yes, even classes are objects in Ruby, and yes, that does get a bit confusing). The object's "type" is determined by this reference to the class object and the object's identity, what makes it difference from all of the other objects of the same type, by its instance variables and other data.
Let's look at something a bit more transparent. Here's we'll define our own class called Person. Each person has a name, stored in the @name instance variable. We'll create several people, each will be separate and distinct objects with differing instance variables, but all will be of the same class. The instance variable will be set using the initialize method, the constructor method for Ruby objects.
class Person def initialize(name) @name = name end def name @name end end a = Person.new("Alice") b = Person.new("Bob") c = Person.new("Carol") puts a.name
First thing to notice here is the class keyword. This tells Ruby that you're defining a new class called Person. Remember to start your class names with a capital letter, class names in Ruby must be constant. Everything inside this block-like syntax is executed in the context of the Class object. This is at odds with languages like C++ and Java, where things inside of a class statement happen at compile time. Remember that Ruby has no concept of "compile time" vs. "run time," so all of the statements inside the class statement are statements being executed in the context of the Class object called Person. Though only def statements are used here, it's a common Ruby idiom to run methods that will actually define more methods, as you'll see later.
When you define methods inside of a class statement, you're defining instance methods. Instance methods are methods called on instances of this class (the objects stored in the variables a, b and c). The initialize method is special, it's called by the class method (a method called on the class object) Person.new after a new object is created. When a new object is created it's blank, it has no instance variables. This is our chance to set some instance variables and give the object an identity. Any parameters passed to the Person.new method are then passed to Person#initialize on the new object, so we'll have access to the names we passed when creating the new objects. We'll simply set the @name instance variable with the person's name.
The name method is a simple instance method. Only instance methods have access to instance variables, so we define a method that does nothing but return the @name instance variable. There is a better and more expressive way to do this though, which will be discussed later.
After the class statement is ended, we go ahead and create three instances of the class Person (otherwise known as three object of the class Person). These three objects each have their own identity in the form of differing instance variables (different names). Anything that's done to any of these objects will not affect the other objects. They do all have a reference to the same class, however. They're all Person objects, and anything done to the Person class (such as adding or changing its instance methods) will change all of the objects.