Rubyのクラスについての復習

前回Rubyのクラスについての理解がふんわりとしていたので、改めて勉強しました。

[はじめてのRuby](http://www.oreilly.co.jp/books/9784873113678/)
[メタプログラミングRuby](https://www.oreilly.co.jp/books/9784873117430/)

## includeとextend
> インクルードとは、指定されたモジュールの定義 (メソッド、定数) を引き継ぐことです。
[instance method Module#include](http://docs.ruby-lang.org/ja/2.2.0/method/Module/i/include.html)

```rb
module Foo
  def foo
  end
end

class Bar
end

bar = Bar.new

p bar.respond_to?(:foo) # => false

class Bar
  include Foo
end

p bar.respond_to?(:foo) # => true
```

includeはメソッド定義を引き継ぐ、とあるので、moduleのなかにあるメソッドをそのままincludeしたクラスのなかに展開するイメージだとわかりやすいと思います。（でも、あくまでも理解しやすい為のイメージです）

```rb
class Bar
  include Foo
end
#    ↓こんな感じです。
#class Bar
#  def foo
#  end
#end
```

じゃあ、クラスメソッドをincludeでクラスに持たせたい時は？

```rb
module Foo
  def self.foo_foo
  end
end

class Bar
  include Foo
end
#   ↓こんな感じを期待している
#class Bar
#  def self.foo_foo
#  end
#end

p Bar.respond_to?(:foo_foo) # => false
```

ここは期待通りの結果にはならないみたいです。では、クラスメソッドとして定義されたメソッドはどこに行ったのかというと、moduleであるFooのクラスメソッドになっています。

```rb
module Foo
  def self.foo_foo
  end
end

class Bar
  include Foo
end

p Bar.respond_to?(:foo_foo) # => false
p Foo.respond_to?(:foo_foo) # => true
```

includeはmoduleのインスタンスメソッドをincludeしたクラスに引き継ぐ、もののようです。
moduleのメソッドをincludeで、対象クラスのクラスメソッドとして引き継がせたい時に登場するのが特異クラスです。

```rb
module Foo
  # インスタンスメソッドとして定義しておく
  def foo_foo
  end
end

class Bar  #Barクラスをオープンして
  class << self  # Barクラスの特異クラスをオープンしてそこにinclude
    include Foo
  end
end

p Bar.respond_to?(:foo_foo) # => true
```

Barクラスの特異クラスをオープンして、特異クラスのインスタンスメソッド　(Barのクラスメソッド)として追加する。
急に出てきた特異クラスというものは、クラスメソッドが定義されている場所です。

```rb
class Bar
  
  # ここにBarクラスのインスタンスメソッドが定義される
  def bar
  end

  class << self # 特異クラスをオープン
    # ここにBarクラスのクラスメソッドが定義される
    def bar_bar
    end
  end
end
```

クラスメソッドの分かりにくさは構文の定義方法が~~３つある~~、というのも理由の一つかと思います。

追記
特異メソッドの定義方法は、実質的には２つではないかというご指摘をいただきました。

```rb
class Bar
  # 特異クラスにメソッドを定義するクラスメソッドの構文

#　↓　def (オブジェクトを表す式).(メソッド名) の形式
  def self.bar_bar
  end

  def Bar.bar_bar
  end

#　↓　特異クラスの中で定義
  class << self
    def bar_bar
    end
  end

  #結果的に同じことです。
end
```

このクラスの特異クラスにインスタンスメソッド（クラスのクラスメソッド）を追加することを、クラス拡張というそうです。

この特異クラスというものはすべてのオブジェクトにあるそうです。

```rb
class Bar
end

bar = Bar.new

p bar.respond_to?(:bar) # => false

class << bar # barオブジェクトの特異クラスをオープン
  # berオブジェクトの特異クラスに特異メソッドを定義
  def bar
  end
end

p bar.respond_to?(:bar) # => true


bar_bar = Bar.new # 同じクラスの別のインスタンスオブジェクト

p bar_bar.respond_to?(:bar) # => false 
```

これはオブジェクト拡張と呼ばれるそうです。

クラスの場合もオブジェクトの場合も特異クラスの開き方とメソッドの定義の仕方は同じみたいです。
上記の例で言えば、クラス名`Bar`はクラスオブジェクトを参照する定数オブジェクトで、参照先はクラスオブジェクト(Classクラスのインスタンスオブジェクト)。変数`bar`はクラスのインスタンスオブジェクトです。ややこしいですが、どちらもオブジェクトなので、特異クラスをもっているということです。

特異メソッドとクラスメソッドは同じ物を指す言葉です。
クラス拡張に対してはクラスメソッドと言い、オブジェクト拡張に対しては特異メソッド、と言い分けているのかな？と思います。

次はextendです。
と言ってもextendが何をする物なのかはもう出ています。

> 引数で指定したモジュールのインスタンスメソッドを self の特異 メソッドとして追加します。
[instance method Object#extend](http://docs.ruby-lang.org/ja/2.2.0/method/Object/i/extend.html)

```rb
module Foo
  def foo
  end
end

class Bar
end

bar = Bar.new

p bar.respond_to?(:foo) # => false

bar.extend Foo # 特異クラスにメソッドを追加。

p bar.respond_to?(:foo) # => true

bar_bar = Bar.new

p bar_bar.respond_to?(:foo) # => false
```

```rb
module Foo
  def foo
  end
end

class Bar
  extend Foo # 特異クラスにメソッドを追加
end

p Bar.respond_to?(:foo) # => true
```

特異クラスをオープンしてincludeをする例を見た後なら、理解しやすい動きだと思います。
特異クラスを開かずに特異クラスにメソッドを追加するメソッドがextendのようです。