ER 6 Know How Ruby Build Inheritance Hierarachies


memo
> - To find a method, Ruby only has to search up the class hierarchy. If it doesn't find the methods it's looking for it starts the search again, trying to find the method_missing method.
- Including medules siletnly creates singleton classes that are inserted into the hierarchy above the including class.
- Singleton methods (class methods and per-object methods) are stored in singleton classes that are also inserted into the hierarchy.

> Effective Ruby



## object
An object is a container of variables. These variables are referred to as instance variables and represent the state of an object. Each object has a special, internal variable that connects it to one and only one class. 

## class
A class is a container of methods and constatns. Classes are themselves objects. So each class is also a contaner of variables called class variables.


## superclass
If class B inherits from class A, then A is the superclass of B. Classes have special, internal variables to keep track of their superclasses.

## module
A module is identical to a class in all respects but one. So like classes, modules are objects and are instances of a particular class. While classes are instances of the Class class, modules are instances of the Module class.

Module have many uses in Ruby but for now we're only concerned with how they contribute to the inheritance hieratchy. Althrough Ruby doesn't directrly support multiple inheritance, modules can be mixed into a class with the include method. which has a similar effect.


## signleton calss
A singleton class is a confusing term for an anonymous and invisible class in the inheritance hierachy.

They are sometimes referred to as eigenclass or metaclass. Even the source code for the Ruby interperter uses these terms interchangeably.


Singleton classes play important role in Ruby, such as providing a place to store class methods and included from modules. Unlike other classes, they're created dynamically on an as-needed basis by Ruby itself.


## receiver
A receiver is the object on which a method is invoked.

## Experiment

Create `Person` class and `Customer` class which inherits `Person`. Interesting thing here is singleton class is created automatically. 

`ancestors` shows inherit order. Righ side is super class of left side. http://ruby-doc.org/core-2.3.0/Module.html

`included_modules` shows what modules are included for this class. Based on `ancestors` and `included_modules`, inherit relationship is as follows.

```
BasicObject
<- Kernel (module)
<- PP::ObjectMixin(module)
<- Object
<- Person
<- Customer
```

oh. Another interesting thing, we can redefine class in runtime.

If multiple modules are included, these inherit relationship is LIFO. Module's class is Object.



```ruby
[3] pry(main)> class Person
[3] pry(main)*   def hi
[3] pry(main)*     puts 'hi'
[3] pry(main)*   end
[3] pry(main)* end

[4] pry(main)> class Customer < Person
[4] pry(main)* end


[11] pry(main)> Customer.superclass
=> Person

[12] pry(main)> Customer.singleton_class
=> #<Class:Customer>

[13] pry(main)> Customer.ancestors
=> [Customer, Person, Object, PP::ObjectMixin, Kernel, BasicObject]

[14] pry(main)> Customer.included_modules
=> [PP::ObjectMixin, Kernel]

[16] pry(main)> module PersonMixin
[16] pry(main)*   def name
[16] pry(main)*     puts 'foo'
[16] pry(main)*   end
[16] pry(main)* end

[18] pry(main)> Person.superclass
=> Object

[19] pry(main)> Customer.ancestors
=> [Customer, Person, PersonMixin, Object, PP::ObjectMixin, Kernel, BasicObject]

[20] pry(main)> module PersonMixin2
[20] pry(main)*   def name
[20] pry(main)*     puts 'bar'
[20] pry(main)*   end
[20] pry(main)* end
=> :name

[21] pry(main)> class Person
[21] pry(main)*   include PersonMixin
[21] pry(main)*   include PersonMixin2
[21] pry(main)* end
=> Person

[22] pry(main)> Customer.ancestors
=> [Customer,
 Person,
 PersonMixin2,
 PersonMixin,
 Object,
 PP::ObjectMixin,
 Kernel,
 BasicObject]
 
[28] pry(main)> Customer.superclass
=> Person

[29] pry(main)> Customer.superclass.superclass
=> Object

[30] pry(main)> Customer.superclass.superclass.superclass
=> BasicObject

[31] pry(main)> Customer.included_modules
=> [PersonMixin2, PersonMixin, PP::ObjectMixin, Kernel]

[37] pry(main)> customer = Customer.new
=> #<Customer:0x007f9de428f008>
[38] pry(main)> def customer.name
[38] pry(main)*   "baz"
[38] pry(main)* end

[42] pry(main)> customer.singleton_methods
=> [:name]

[43] pry(main)> customer.name
=> "baz"
```