【Ruby/namespace】Rubyでよく見る「:: ←これ」を深ぼる

# 概要
現在、プログラミング言語RubyとそのWebフレームワークRuby on Railsを学習中です。
その中でよく見かける記号があります。

``::``←これです。

* ``Devise::RegistrationsController``や
* ``ActiveHash::Base``や
* ``ActiveRecord::Migration``など

初学者目線でいうと「クラス名とかでよく見るな」くらいにしか思ってなかったこの記号。
もちろんですが、ちゃんと意味があります。

この記事ではその概要について紹介します。

<br>

# ::←これの正体

さて、特に意識することなく使っていた「::」←これ、ですが。
理解するには``名前空間``という概念を知る必要があります。

## 名前空間とは？
では、名前空間とは何でしょうか？
簡単に言うと``メソッドや変数を管理する範囲``のことです。
同じ``話す``でもアメリカと日本では言葉が違いますし、同じ``太郎``でも1組と2組の太郎は別人です。

このように、``同じ名前であることによるコンフリクト(衝突)が起きないように「どこに属するメソッド、変数ですか？」というのを明記する仕組み``が名前空間です。

ここまでくるとわかってきたと思いますが、``〇〇::△△``は``〇〇に属する△△``という意味となります。

``Device::ResistrationsController``は``Deviseに属するResistrationsController``と読むことができます。

また、``名前空間は「クラス」か「モジュール」単位で区分けをします``。
ここでは詳しい説明を省きますが、クラスとモジュールには次の違いがあります。

* クラス : 実体化できる (実体に固有の値やメソッドを定義できる)
* モジュール : 実体化できない

> @scivola 様からご指摘をいただきました点について
下記で修正を加えています。



<br>

## :: の意味 / 具体例


これまでの内容で、``::``は``A::B``の使い方をすることで、``Aに属するBを呼び出す``という意味となることがわかりました。

もう少し詳しく見ると、``::``には次の2つの意味合いがあります。

```
1. クラス・モジュールに属する定数の呼び出し
2. クラス・モジュールに属するメソッドの呼び出し
```

では、それぞれの例について見ていきましょう。

<br>

### 1. Mathモジュールの定数PIを参照する

Rubyの組み込みライブラリであるMathモジュールに属する定数PIを呼び出して、円周率を出力してみましょう。
(参照 : <a href="https://docs.ruby-lang.org/ja/latest/class/Math.html">Rubyリファレンス | module Math</a>)

```call_pi.rb
puts Math::PI
```

このプログラムを実行します。

```:terminal
% ruby call_pi.rb
3.141592653589793
```

``円周率π``を出力することができました。

定数を参照する場合はこのように使用します。

余談ですが、後の例に備えて、別な形での呼び出しを試してみます。
メソッドの呼び出しのように「.(ドット)」で呼び出してみます。

```call_pi.rb
puts Math.PI
```

このプログラムを実行すると…

```:terminal
% ruby call_pi.rb
Traceback (most recent call last):
math.rb:1:in `<main>': undefined method `PI' for Math:Module (NoMethodError)
```

``MathモジュールにPIというメソッドが定義されていません``というエラーです。
PIは定数 (値) であってメソッドではないのでこのようなエラーが出ると考えられます。

<br>

### 2. 動物クラス (自作) の「走る」メソッドを参照する

続いて「メソッド参照」の例を見てみましょう。

* いぬは4足で走る
* 人間は2足で走る

この例では名前空間があることの恩恵を知るために、まずは名前空間無しで書いてみましょう。

```run.rb
def run
  puts '4足で走ります'
end

def run
  puts '2足で走ります'
end

run
run
```

このプログラムを実行してみましょう。

```:terminal
% ruby run.rb
2足で走ります
2足で走ります
```

同じ``run``というメソッド名を使い回すと、より後に定義されたメソッドが参照されます。

ではこれらの``run``を``Dog`` ``Human``クラスで区切って定義してみましょう。

```run.rb
class Dog
  def self.run
    puts '4足で走ります'
  end
end

class Human
  def self.run
    puts '2足で走ります'
  end
end

Dog::run
Human::run
```

このプログラムを実行してみます。

```:terminal
% ruby run.rb
4足で走ります
2足で走ります
```

名前空間に沿ったメソッドが参照されました。
これはクラスを定義し、``::``を使ったことで、``Dogのrunを参照します``のように、レシーバを指定して呼び出せるようになったためです。

ちなみにこの``::``の使い方 (メソッド呼び出し) の場合は、「.(ドット)」で代替することができます。
具体的には次の通りです。

```run.rb
(省略)
Dog.run
Human.run
```

```:terminal
% ruby run.rb
4足で走ります
2足で走ります
```

クラスメソッド呼び出しと同じ動作をする、ということがわかりました。

そして``::``を``「メソッド呼び出し」``として用いる場合は、クラスやモジュール以外もレシーバに指定することができます。

例えばこんな感じ。

```sample.rb
10::times { |i| puts i }
```

```:terminal
% ruby sample.rb
0
1
2
3
4
5
6
7
8
9
```

以上が、``::``の使い方と、その意味です。

<br>

# まとめ
* ``::``←これはメソッドや変数がどこに従属するかを示す記号
* 名前空間はメソッドや変数の利用範囲を指定する仕組み
* 名前空間はクラスやモジュールで区切る

Railsは便利な半面、自分でカスタマイズしようとするときは意外と苦労するなと感じています。
そしてその原因の大半は``Rubyの基礎を知らないこと``なのかなーと。

短い時間でキャッチアップすることも大事ですが、腰を据えて基本を理解するのも重要ですね。バランスをとりながら学習を進めようと思います。

<br>

# 参照
* <a href="https://railsguides.jp/autoloading_and_reloading_constants.html#%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE%E6%A7%8B%E9%80%A0">Railsガイド | 定数の自動読み込みと再読み込み (Zeitwerk)</a>
* <a href="https://techacademy.jp/magazine/22391">TechAcademy | Rubyの名前空間</a>