【Ruby】モジュールとは

モジュールについてわからなすぎたので、簡単にまとめます。

## 参考文献
「[プロを目指す人のためのRuby入門](https://www.amazon.co.jp/%E3%83%97%E3%83%AD%E3%82%92%E7%9B%AE%E6%8C%87%E3%81%99%E4%BA%BA%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AERuby%E5%85%A5%E9%96%80%EF%BC%BB%E6%94%B9%E8%A8%822%E7%89%88%EF%BC%BD-%E8%A8%80%E8%AA%9E%E4%BB%95%E6%A7%98%E3%81%8B%E3%82%89%E3%83%86%E3%82%B9%E3%83%88%E9%A7%86%E5%8B%95%E9%96%8B%E7%99%BA%E3%83%BB%E3%83%87%E3%83%90%E3%83%83%E3%82%B0%E6%8A%80%E6%B3%95%E3%81%BE%E3%81%A7-Software-Design-plus-%E4%BC%8A%E8%97%A4-ebook/dp/B09MPX7SMY/ref=sr_1_6?dib=eyJ2IjoiMSJ9.8ruGcwLFNR6ZSEDDcKuhWXvEXrbFTyOsIgjHHUsCEsqTza7D794_8QnAuR2zBVlOZIy_FxMMuFVH4gFojlkB3YnMK-FgPDL40XlCw4O3l0B_qi4Gljx-HbGv76NXmvH1gb185Iz1hnlmAx9Fld07qmuCkQAklMwncZIdAbBCf3IFXMpv_arhYYPjQ_nrfqbtErfQtKfHwrm6p6fm2BHj6LdQH0JHASTTX94gVVblgHM.voXdiIjeMrEH8EyFvGtt14J9sHXC57zo98XY_Tym5G0&dib_tag=se&qid=1734077834&refinements=p_n_feature_seven_browse-bin%3A3232401051&s=books&sr=1-6 "プロを目指す人のためのRuby入門")」
こちらを読みながら、わかったことをまとめます。

---

### モジュールとは
モジュールは、Rubyにおけるコードを整理・グループ化する仕組み。
主に下記の３つのことができる。
- **1. 継承を使わずに、メソッドを使用できる（include・Mix-in）**。
- **2. モジュール内のメソッドをクラスメソッドとして追加する（extend）**。
- **3. モジュールを名前空間として使い、クラスやメソッドの衝突を防ぐ。（名前空間=name_space）**

---

### 1. Mix-in
継承を使わずにメソッドを共有する仕組み。
Rubyは単一クラス(スーパークラス)しかない。
```Ruby
# ユーザーを表すクラス
class User
    # 省略
end

# 注文を表すクラス
class Order
  # 省略
end
```

ユーザクラスと注文クラス内に同じコードがあったとしても、
この2つのクラスは`is-a`関係(〜は〜である)でないので、継承できない。
**⇒ Mix-in(include)を使えば解決する。**

```Ruby
# ログ機能を提供するモジュール
module Logger
  # 下記がユーザ・注文どちらのクラスでも書かれてるので、モジュール内に書く
  def log(message)
    puts "[LOG] #{message}"
  end
end

# ユーザーを表すクラス
class User
  # Mix-in
  # コード繰り返し書く必要なくなる
  include Logger
end

# 注文を表すクラス
class Order
  # Mix-in
  # コード繰り返し書く必要なくなる
  include Logger
end
```

また、 **`include`** だと **`インスタンスメソッド`** として追加される。

### `インスタンスメソッド`とは：
インスタンスに属するメソッドで、インスタンスを生成しないと使えない。

**`「インスタンス」`**：
クラスから作成する１個の個体・実体。
「.new」でクラスから、新しいインスタンスを作成する。

**`「メソッド」`**：
そのクラスでやりたいこと。処理のまとまり。
何回もコードを書かなくて済むように、クラス内に書いて、
他のインスタンス（個体）にも同じ処理をさせる。

---

### 2. extend
モジュール内のメソッドを
**クラスそのものをメソッドとして**（クラスメソッド）追加される。

**`クラスメソッド`とは**
クラスに属するメソッドで、インスタンスを生成せずに直接クラスから使える。

### includeとの違い

![モジュール.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3905096/301d2762-c84b-1959-8b30-09c308136d38.jpeg)


```Ruby
# モジュールの定義
module Greeting
  def say_hello
    "こんにちは！"
  end
end

#################################################

# 【include】を使用したクラス
class User
  # インスタンスメソッドとして追加
  include Greeting 
end

# 【include】：インスタンスメソッドを呼び出せる
# つまり、インスタンス経由でメソッドを呼び出す
user = User.new # インスタンスを生成
puts user.say_hello  

#################################################

# 【extend】を使用したクラス
class Admin
  # クラスメソッドとして追加
  extend Greeting 
end

# 【extend】：クラスでメソッドを呼び出せる
# つまり、クラスそのものでメソッドを呼び出す（インスタンスメソッド不要）
puts Admin.say_hello  # => "こんにちは！" （クラスメソッド）
```

| **操作**      | **取り込まれる場所**       | **呼び出し元**              | **結果**           |
|---------------|----------------------------|-----------------------------|--------------------|
| `include`     | クラスのインスタンス       | インスタンス（`User.new`）   | インスタンスメソッド |
| `extend`      | クラスそのもの（特異クラス）| クラス（`Admin`）            | クラスメソッド      |

---

### 3. 名前空間(name_space)
クラス名がかぶってしまった時、そのモジュールに属するクラスにすることで、
他のプログラム・ライブラリと、クラス名やメソッド名の衝突を防ぐことができる。

```ruby
module Admin
  # Adminモジュールに属するクラスなので、
  # クラス名Userが被ってても、区別できる。
  class User
    def role
      "管理者"
    end
  end
end

module Guest
  # Guestモジュールに属するクラスなので、
  # クラス名Userが被ってても、区別できる。
  class User
    def role
      "ゲスト"
    end
  end
end

# 動作確認
admin_user = Admin::User.new
guest_user = Guest::User.new

puts admin_user.role  # => "管理者"
puts guest_user.role  # => "ゲスト"
```