モジュールのミックスイン

# ２つのクラスの同じ処理 log(text)
```rb
irb(main):001* class Product
irb(main):002*   def title
irb(main):003*     log 'title is called.'
irb(main):004*     'A great movie'
irb(main):005*   end
irb(main):006*
irb(main):007*   private
irb(main):008*   def log(text)
irb(main):009*     puts "[LOG] #{text}"
irb(main):010*   end
irb(main):011> end
=> :log
irb(main):012* class User
irb(main):013*   def name
irb(main):014*     log 'name is called.'
irb(main):015*     'Alice'
irb(main):016*   end
irb(main):017*
irb(main):018*   private
irb(main):019*
irb(main):020*   def log(text)
irb(main):021*     puts "[LOG] #{text}"
irb(main):022*   end
irb(main):023> end
=> :log
irb(main):024> product = Product.new
=> #<Product:0x0000000110153158>
irb(main):025> product.title
[LOG] title is called.
=> "A great movie"
irb(main):026> user = User.new
=> #<User:0x0000000113ac8488>
irb(main):027> user.name
[LOG] name is called.
=> "Alice"
```

>どちらもログを出力することはできましたが、`ログを出力する処理は重複`しています。

### is-aの関係が成り立たないのであれば、継承の使用は避けるべき
>しかし、コードの重複しているからといって安易に継承を使ったりしてはいけません。`「製品はユーザである」または「ユーザは製品である」という関係(is-aの関係)が成り立たないのであれば、継承の使用は避ける`べきです。

### モジュールの使い所
>`継承は使えないが、「ログを出力する」という共通の機能は持たせたい`そんな時に選択肢として挙がるのがモジュールです。


# is-aの関係が成り立たなければ継承は避ける
```rb
irb(main):001* module
irb(main):001* module Loggable
irb(main):002*   def log(text)
irb(main):003*     puts "[LOG] #{text}"
irb(main):004*   end
irb(main):005> end
=> :log
irb(main):006>
irb(main):007* class Product
irb(main):008*   include Loggable
irb(main):009*
irb(main):010*   def title
irb(main):011*     log 'title is called.'
irb(main):012*     'A great movie'
irb(main):013*   end
irb(main):014> end
=> :title
irb(main):015* class User
irb(main):016*   include Loggable
irb(main):017*
irb(main):018*   def name
irb(main):019*     log 'name is called.'
irb(main):020*     'Alice'
irb(main):021*   end
irb(main):022> end
=> :name
irb(main):023> product = Product.new
=> #<Product:0x000000010df18750>
irb(main):024> product.title
[LOG] title is called.
=> "A great movie"
irb(main):025> user = User.new
=> #<User:0x000000010df81520>
irb(main):026> user.name
[LOG] name is called.
=> "Alice"
```
>Loggableモジュールをincludeすることで、モジュールに定義したlogメソッドをProductクラスでもUserクラスでも呼び出すことができました。このモジュールがあれば、これら２つのクラスに限らず、他のクラスでも継承関係を気にすることなくログ出力の機能を持つことができます。
### ミックスインで複数のクラスにインクルードできる
>　このようにモジュールをクラスにincludして機能を追加することをミックスインと言います。`ミックスイン先のクラスは基本的にどんなクラスでもOK`です。また、`一つのクラスに複数のモジュールをミックスイン`することもできます。
```rb
irb(main):001* module
irb(main):001* module Loggable
irb(main):002*   private
irb(main):003*
irb(main):004*   def log(text)
irb(main):005*     puts "[LOG] #{text}"
irb(main):006*   end
irb(main):007> end
=> :log
irb(main):008* class Product
irb(main):009*   include Loggable
irb(main):010*
irb(main):011*   def title
irb(main):012*     log 'title is called.'
irb(main):013*     'A great movie'
irb(main):014*   end
irb(main):015> end
=> :title
irb(main):016> product.log
(irb):16:in <main>': undefined local variable or method `product' for main:Object (NameError)

product.log
^^^^^^^
...
irb(main):017> product = Product.new
=> #<Product:0x00000001127bc4c0>
irb(main):018> product.log
(irb):18:in <main>': private method `log' called for #<Product:0x00000001127bc4c0> (NoMethodError)

product.log
       ^^^^
#<Product:0x00000001127bc4c0> (NoMethodError)

product.log 'public?'
       ^^^^
```       

# 感想
モジュールのミックスインはすごい。
railsのAPIも読めそうな気がする。