【Ruby】class << selfでなぜクラスメソッドが定義できるのか

## はじめに
いきなりですが、Rubyでクラスメソッドを定義する際に、`class << self`と記述したことはありますか？
おそらく、Rubyを使ったことのある人であれば、一度は記述したことがあると思います。

この`class << self`について、僕の中では

- クラスメソッドを定義するときの構文である
- この中に書けばいちいち`self`を書く必要がない

というぐらいの浅い知識でしかなかったのですが、詳しく調べてみると`class << self`でなぜクラスメソッドが定義できるのか知見が得られたため、この記事にまとめようと思います。

### この記事の構成
この記事では以下の2点をまとめることで、表題について理解していこうと思います。

1. Rubyのクラスメソッドがどのように定義されるのか
1. `class << self`とは何なのか

### この記事の対象者
この記事の対象者は以下の通りです。

- Rubyのクラスメソッドがどのように定義されるのか詳しく知らない人
- 僕と同じように`class << self`はクラスメソッドを定義するときの構文というくらいの知識しかない人

それでは、頑張っていきましょう。

## Rubyのクラスメソッドがどのように定義されるのか
いきなり`class << self`の説明を見ても、Rubyのクラスメソッドがどのように定義されるのかを知らないと説明が理解できないため、まずはクラスメソッドがどのように定義されるのかを説明します。

### 特異メソッドが分かればクラスメソッドが分かる
特異メソッド？
クラスメソッドと違うのでは？
何で特異メソッドについて知る必要があるの？

と思うかもしれませんが、特異メソッドを知ることが、クラスメソッドを知ることに繋がるため、まずは特異メソッドについて説明します。

#### 特異メソッドって何？
そもそも**特異メソッド**とは何でしょうか？
端的に言うと、**特定のオブジェクトだけが持つメソッド**のことです。

#### 特異メソッドを定義する
上の説明だけでは伝わりにくいと思いますので、実際に特異メソッドを定義するコードを見てみます。

```rb
name = 'tomoprog'

# 特異メソッドを定義する
def name.strong
  "** #{self} **"
end

puts name
puts name.strong
```
```:実行結果
tomoprog
** tomoprog **
```

今回では`name`が特定のオブジェクトにあたります。
つまり、**ここで定義した`strong`というメソッドは`name`だけが持つメソッドとして定義されます。**
`name`以外のオブジェクトで`strong`メソッドを実行した場合にどうなるか見てみましょう。

```rb
name = 'tomoprog'
another = 'another' # name以外のオブジェクト

# 特異メソッドを定義する
def name.strong
  "** #{self} **"
end

puts name
puts name.strong
puts another.strong # これは実行できる？
```
```:実行結果
undefined method `strong' for "another":String (NoMethodError)
```

`NoMethodError`となり、`name`以外のオブジェクトでは`strong`メソッドが存在しないことが分かると思います。

#### 特異メソッドはどこに定義されるのか
特異メソッドを定義することで、特定のオブジェクトにだけメソッドを定義できることは分かりました。
それでは、この特異メソッドがどこに定義されるのか、もう少し詳しく見てみましょう。

特異メソッドを定義するとそのメソッドは**メソッドを定義したオブジェクトの特異クラス**というクラスに定義されます。

先程の例をもとに図で説明すると、下のようになります。

![スクリーンショット 2020-05-01 11.11.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68663/ed38573e-b14e-655e-414f-aa818aaa1624.png)

ちなみに、**特異クラスは特異メソッドを定義したときに自動で生成される**ため、`another`オブジェクトの特異クラスはまだ生成されていません。

それでは、実際に特異クラスにメソッドが定義されているのかを確認してみましょう。
特異クラスを参照するには`Object#singleton_class`を使用します。

```rb
name = 'tomoprog'

# 特異メソッドを定義する
def name.strong
  "** #{self} **"
end

puts name.singleton_class # これで特異クラスを参照できる
puts name.singleton_class.method_defined? :strong
```
```:実行結果
#<Class:#<String:0x0000000001a24490>>
true
```

この結果から特異クラスに`strong`メソッドが定義されていることが分かると思います。

#### クラスに特異メソッドを定義する
特異メソッドの定義方法が分かったところで、今度はクラスに特異メソッドを定義してみましょう。

```rb
class NamePrinter; end
def NamePrinter.strong(name)
  "** #{name} **"
end

puts NamePrinter.strong('tomoprog')
```
```:実行結果
** tomoprog **
```

ここで、`strong`メソッドの呼び出し方をよく見てください。
**クラスメソッドの呼び出し方と全く同じ**であることが分かると思います。
つまり、**クラスメソッドの正体はクラスの特異メソッドである**ということです。[^1]
[^1]: もっと詳しく言うと、Classクラスのオブジェクトの特異メソッドと言えますが、Classクラスからのオブジェクトの生成を説明していないため、ここではクラスの特異メソッドという表現にしています。詳しく知りたい方はClassクラスからクラスを生成する方法を調べてみてください。

これをクラス定義式の中に書くと、

```rb
class NamePrinter
  def NamePrinter.strong(name)
    "** #{name} **"
  end
end
```

さらに`NamePrinter`を`self`に変えれば、

```rb
class NamePrinter
  def self.strong(name)
    "** #{name} **"
  end
end
```

よく見るクラスメソッドの定義方法と同じになることが分かると思います。

## `class << self`とは何なのか
ここまでの説明で、クラスメソッドが特異メソッドであるということは理解いただけたでしょうか？

クラスメソッドが特異メソッドであることが分かると`class << self`の説明も理解できるようになります。

この`class << self`という記述は[**特異クラス定義式**](https://docs.ruby-lang.org/ja/latest/doc/spec=2fdef.html#singleton_class)と呼ばれ、指定したオブジェクトの特異クラスをクラス定義式と同じように記述できるものです。

指定したオブジェクトというのは`<<`の右側に書いてあるオブジェクト、つまり`class << self`であれば、`self`の特異クラスをクラス定義式と同じように記述できるということです。

つまり、`class << self`は`self`の特異クラスにメソッドを定義することで、特異メソッドを定義しているのです。

### 特異クラス定義式でメソッドを定義する
それでは、実際に特異クラス定義式でメソッドを定義してみましょう。

```rb
class NamePrinter; end
class << NamePrinter
  def strong(name)
    "** #{name} **"
  end
end

puts NamePrinter.strong('tomoprog')
```
```:実行結果
** tomoprog **
```

`class << NamePrinter`で`NamePrinter`の特異クラスに対してメソッドを定義することで、`NamePrinter`の特異メソッドを定義しています。

これを先ほどと同じようにクラス定義式に入れてあげると

```rb
class NamePrinter
  class << NamePrinter
    def strong(name)
      "** #{name} **"
    end
  end
end
```

さらに`NamePrinter`を`self`に変えれば、

```rb
class NamePrinter
  class << self
    def strong(name)
      "** #{name} **"
    end
  end
end
```

見慣れた`class << self`になりました。

## まとめ

- クラスメソッドとはクラスの特異メソッド（特異クラスに定義されたメソッド）である
- `class << self`は`self`の特異クラスに対してメソッドを定義している

`class << self`について調べることで、Rubyのクラスメソッドについての知見が今までよりも得られたと思います。

この記事がRubyを使ってなんとなくクラスメソッドを定義している人に少しでも役にたてば幸いです。

それではまた。
TomoProg

## 参考
- [Ruby 初級者のための class << self の話 (または特異クラスとメタクラス)](https://magazine.rubyist.net/articles/0046/0046-SingletonClassForBeginners.html)
- [パーフェクトRuby 第２版 第６章 Rubyのクラスオブジェクト](https://gihyo.jp/book/2017/978-4-7741-8977-2) 
- [特異クラス定義式](https://docs.ruby-lang.org/ja/latest/doc/spec=2fdef.html#singleton_class)