# Everything in Ruby is an `Object`, even classes, modules and methods.
# Despite that, an `Object` can't exist without a class.
# Classes are instances of the `Class` class.
# The `Class` class is an instance of `Class` :). It holds a reference
# to itself.
# All objects are instances of the `Object` class. `Object` itself
# is a class, so its an instance of the `Class` class.
# Despite that `Class` inherits from `Module` which
# in turn inherits from `Class`.
# It's very intertwined because the building blocks of Ruby
# so `Object`, `Module` and `Class`
# all reference each other in an endless loop.
# Only instances of `Module` and `Class` can hold methods in Ruby.
# Objects themselves don't hold any direct references to their methods.
# They only possess a reference to their class, from which they
# take their instance methods.
# Despite that, it's possible to extend objects with custom methods that
# are only available to that particular object.
# That's when the `singleton`, `eigen` or `meta` class comes in.
# (Almost) every Ruby object has two classes!
# One of them is the regular class available by the `#class` method,
# which holds instance methods of the object.
# The other class is available by the `#singleton_class` method.
# This class holds methods that are only available to this object.
# Every Ruby object has a unique singleton class. That's why methods
# defined in it are only available to one object.
class Foo
def some_instance_method
puts "it's me, some_intance_method"
end
end
foo = Foo.new
foo.some_instance_method #=> it's me, some_intance_method
# you can define singleton methods
# (methods unique to a particular object)
# like so
def foo.unique_method
puts "I'm unique!"
end
# it's only available to that particular object
foo.unique_method #=> "I'm unique"
Foo.new.unique_method #=> undefined method `unique_method' (NoMethodError)
# the unique method is not a regular method
foo.methods.include?(:unique_method) #=> false
# it's a singleton methods
foo.singleton_methods #=> [:unique_method]
# which means that it's defined on the singleton class
foo.singleton_class.instance_methods.include?(:unique_method) #=> true
# there is an alternative syntax which let's you open the body
# of a singleton class directly and call/define methods on it
class << foo
def another_singleton_method
puts "I'm another_singleton_method"
end
# since it's the singleton classes body
# you can call class methods on it
attr_accessor :bar
end
foo.singleton_methods
#=> [:unique_method, :another_singleton_method, :bar]
foo.bar = 3
foo.bar #=> 3