| Did I mention classes were fundamental to Ruby? Well, that was an
 understatement, they are so pervasive that the object model is critical to
 understanding Ruby. |  | 
|  |  class Pet
  attr_accessor :name
 | 
|  |   def initialize(name)
    @name = name
  end
 | 
|  |   def pet
    puts "#{@name} likes that!"
  end
end
 | 
|  |  | 
|  | class Cat < Pet
  def pet
    purr
  end
 | 
|  |  | 
|  |   def purr
    puts "#{@name} purrs!"
  end
end
 | 
| Let’s create a couple of instances | butler = Dog.new("Butler")
spot = Cat.new("Spot")
 | 
| The receiver is in spot, which is of classCat. |  | 
| The message is pet, whichCatdefines. | p spot.class.instance_methods(false)
 | 
| So this will invoke the petmethod fromCat. |  | 
| Indeed spotresponds to the messagepet. |  | 
| The receiver is butler, which is of classDog. |  | 
| The message is pet, whichDogdoes not define. | p Dog.instance_methods(false)
 | 
| so Ruby walks up the ancestry chain.
 The next one is Pet, so this will invoke thepetmethod fromPet. | p Dog.ancestors
#
butler.pet
 | 
| And so the butlerinstance does too respond to the messagepet. | p butler.respond_to? :pet
 | 
| We can see that the methods are not the same. | p spot.method(:pet) == butler.method(:pet)
 | 
| When Ruby does not find a method corresponding to the message, it raises
 NoMethodError. | begin
  spot.jump
rescue NoMethodError => e
  puts e
end
 | 
| When Ruby find a method corresponding to the message, but its visibility is
 incompatible, it also raises NoMethodErrorbut the message is different. | begin
  spot.purr
rescue NoMethodError => e
  puts e
end
 | 
| Using the sendmethod, we can send thepurrmessage directly tospot. |  | 
| This message-oriented approach is what makes Ruby so dynamic. Everything is an object in Ruby, and thus everything has methods. Even classes! |  | 
| In fact, a class is an instance of the class Class. | puts "`Pet` is a #{Pet.class}"
 | 
| And Classitself is an instance of the classClass. | puts "`Class` is a #{Class.class}"
 | 
| And so, it is only natural that we can instantiate classes as well. | snake = Class.new(Pet) do
  def pet
    puts "#{@name} slithers"
  end
end
 | 
| newis a method whose receiver is an instance of the class Class.
 |  | 
| And, snakeinheriting fromPet, it properly responded to theinitializemessage. |  | 
| So newis an instance method on an instance of the classClass, which
 means… it is a class method? |  | 
| Let’s try to define another class method by reopening the class Class. | class Class
  def hello
    puts "hello, I am #{name}"
  end
end
 | 
| It worked! |  | 
| But maybe a bit too much… the change is effective for every instance of
 the class Class, which is… everything! |  | 
| We want class methods that exist only for a specific class, but it can’t be
 defined on the class itelf or it’ll apply to instances of that class, and it
 can’t be defined on the class of that class either, as this is Class, as we
 have just seen. |  | 
|  |  | 
| We would need a new “metaclass” that exists just for that Petclass… |   pet_metaclass = Class.new(Class) do
    def meta_hello
      puts "hello meta"
    end
  end
 | 
| … that we’d instantiate to give us a class to inherit from. |   pet_class = Class.new(pet_metaclass.new) do
    attr_reader :name
 | 
|  |     def initialize(name)
      @name = name
    end
  end
 | 
|  |  | 
| Unfortunately Ruby does not allow us to do that! | rescue TypeError => e
  puts e
end
 | 
| Fortunately Ruby has that answered already. Since that class would exist only
 once for each class, it is a singleton. Therefore the name is the “singleton
 class”, and Ruby creates one for every instance of a class. |  | 
| The class is reachable using <<, which moves the receiver to the singleton
 class of the object passed. | class << Pet
  def hello
    puts "singleton!"
  end
end
 | 
| And this time, it works! |  | 
| The classkeyword changes the receiver to be the class being defined, and
 the receiver is always accessible withself.
 The receiver is accessible viaself, so we can pass that to<<. | class Dog
  class << self
    def bark
      puts "woofleton!"
    end
  end
 | 
| A shorthand exists with defoutside ofclass << self. |   def self.lick
    puts "lickleton!"
  end
end
 | 
|  |  | 
| These are still instance methods, it just so happens that they are instance
 methods of the singleton class for Dog, of which theDogclass is an
 instance of. | p Dog.singleton_class.instance_methods(false)
 | 
| This is visible in the ancestry chain. | p Dog.singleton_class.ancestors.first
 | 
| Every instance gets singleton classes, not just instances of the class
 Class. Here’s one for an instance ofCat. |  | 
| We can access the singleton class of that instance the same way.
 And define methods for just that cat and no other cat. | class << spot
  def jump
    puts "#{@name} jumps!"
  end
end
 | 
|  |  |