Ruby初心者が必ずつまづくオブジェクトモデルの話（include, extendを理解する）

[メタプログラミングRuby 第2版](http://www.amazon.co.jp/%E3%83%A1%E3%82%BF%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0Ruby-%E7%AC%AC2%E7%89%88-Paolo-Perrotta/dp/4873117437/ref=sr_1_1?ie=UTF8&qid=1465262874&sr=8-1&keywords=%E3%83%A1%E3%82%BF%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0ruby+%E7%AC%AC2%E7%89%88), [Effective Ruby](http://www.amazon.co.jp/%E6%9C%AC-Effective-Ruby-Peter-J-Jones/dp/4798139823/ref=sr_1_1_twi_jp__2?ie=UTF8&qid=1465262923&sr=8-1&keywords=EffectiveRuby)のオブジェクト階層・クラス定義などを2、3周読んで、わかったかも！なポイントを書きます。
とりあえずその辺のトピックスを1周して「と・・・特異・・クラス・・？」と恐れおののいた人の理解の助けになれば・・なメモ。

## オブジェクト

- Rubyではすべてのものがオブジェクトである
- クラスもオブジェクトである
- Rubyでたくさん存在しているクラスは、 __Classクラスのオブジェクト__ である

## クラス

- クラスとはモジュールである
- モジュールとクラスの違い、モジュールは ```new``` できない
- つまりモジュールはインスタンス化できない

## モジュール

- モジュールのインスタンスメソッドは、クラスに __```include```__ されると、__インスタンスメソッド__として呼びだせる
- モジュールのインスタンスメソッドは、クラスに __```extend```__ されると、__クラスメソッド__として呼びだせる
- モジュールの__クラスメソッド__は、クラスに ```include``` しても ```extend``` しても呼び出せない
- モジュールのクラスメソッドはモジュールの__特異クラス__に存在するから

### include

- モジュールを __クラス__ に取り込むための機構

### extend

- モジュールを __オブジェクト__ に取り込むための機構
- Rubyの全てのクラスは __Classクラスのオブジェクト__ なので、```extend``` でクラスを拡張できる
- __Classクラスのオブジェクト__ を拡張するための仕組みが __特異クラス__

#### includeとextendの例

```
module MyModule
  def my_instance_method
    'my_instance_method'
  end
  def self.my_class_method  # 呼び出せない
    'my_class_method'
  end
end

class MyIncludeClass
  include MyModule
end

my_include_class = MyIncludeClass.new
my_include_class.my_instance_method
# => "my_instance_method"


class MyExtendClass
  extend MyModule
end

MyExtendClass.my_instance_method
# => "my_instance_method"

```

## メソッド

- メソッドは1種類である
- いろいろ種類があるじゃないかと思うが、どこに存在しているかの違い

### インスタンスメソッド

- オブジェクトから呼びだせるメソッド
- オブジェクトのクラスに存在する

クラスにインスタンスメソッドを定義する例

```
class MyIncludeClass
  def my_method1
    'my_method1'
  end
end
```

※ ```class``` はすでに定義済みのクラス名（例ではMyIncludeClass）が渡されると、再オープンする。オープンしたクラスにメソッドを ```def``` で追加している。

インスタンスメソッドを呼び出してみる例

```
m1 = MyIncludeClass.new
m1.my_method1
=> "my_method1"
```

上の例で ```MyIncludeClass``` は ```include MyModule``` しているので、モジュールのメソッドと、今追加したメソッドがインスタンスメソッドとして定義されている。

定義済みのインスタンスメソッドを確認する例

```
MyIncludeClass.instance_methods  # インスタンスメソッド一覧を表示
# => [:my_method1, :my_instance_method, ...]
```

### クラスメソッド

- クラスから呼びだせるメソッド
- Classクラスのオブジェクト = クラス の特異クラスに存在する

クラスにクラスメソッドを定義する例

```
class MyExtendClass
  def self.my_extend1
    'my_extend1'
  end
end
```

※ ```def self``` とするとクラス定義の中の ```self``` つまりそのクラス自身をレシーバとしたメソッドが定義できる = クラスメソッド

クラスメソッドを呼び出してみる例

```
MyExtendClass.my_extend1
=> "my_extend1"
```

上の例で ```MyExtendClass``` は ```extend MyModule``` しているので、モジュールのメソッドと、今追加したメソッドがクラスメソッドとして定義されている。

定義済みのクラスメソッドを確認する例

```
irb> MyExtendClass.singleton_methods
# => [:my_extend1, :my_instance_method]
```


## 特異クラス

- すべての __オブジェクト__ が裏に持つことができる特別なクラス
- 特異クラスはオブジェクトを __1つしか持てない__ 
- ので __singleton_class__ ともいう
- オブジェクトの特異クラスに存在するメソッドは、オブジェクトの __特異メソッド__ である
- オブジェクト特異メソッドは、オブジェクトのクラスのメソッド（クラスメソッド）である
- つまりクラスは __Classクラスのオブジェクト__ なので、 Classクラスのオブジェクトの__特異クラス__ に定義されたメソッドはそのクラスだけで使える __クラスメソッド__ である

特異クラスの確認方法 : __singleton_class__

```
irb> my_extend_class = MyExtendClass.new
=> #<MyExtendClass:0x007f8c2384cb08> 
irb> my_extend_class.singleton_class
=> #<Class:#<MyExtendClass:0x007f8c2384cb08>>
```

特異メソッドの確認方法 : __singleton_methods__

```
irb> my_extend_class.singleton_class.singleton_methods
=> [:my_extend1, :my_instance_method]
```

特異クラス側からメソッドを確認

```
irb> MyExtendClass.singleton_class.instance_methods
# => [:my_extend1, :my_instance_method, ...]
```

### 特異クラスはオブジェクト階層のどこに入る？

- 特異メソッドの住処が特異クラス
- オブジェクトが特異メソッドを持っていれば、まず特異クラスからメソッド探索される
- 特異クラスもオブジェクト階層に組み込まれる
- 特異クラスの ```superclass``` はオブジェクトの通常のクラス
- 継承したサブクラスからもクラスメソッドが使えるようになる

特異クラスのsuperclassの確認方法

```
irb> my_extend_class.singleton_class.superclass
# => MyExtendClass
```

- - -

これらのポイントを頭の片隅に置きつつ、もう一度 「メタプログラミングRuby」 を読むとRubyわからん・・の闇がパッと晴れる・・！かも。。