概要
現在、プログラミング言語RubyとそのWebフレームワークRuby on Railsを学習中です。
その中でよく見かける記号があります。
::
←これです。
-
Devise::RegistrationsController
や -
ActiveHash::Base
や -
ActiveRecord::Migration
など
初学者目線でいうと「クラス名とかでよく見るな」くらいにしか思ってなかったこの記号。
もちろんですが、ちゃんと意味があります。
この記事ではその概要について紹介します。
::←これの正体
さて、特に意識することなく使っていた「::」←これ、ですが。
理解するには名前空間
という概念を知る必要があります。
名前空間とは?
では、名前空間とは何でしょうか?
簡単に言うとメソッドや変数を管理する範囲
のことです。
同じ話す
でもアメリカと日本では言葉が違いますし、同じ太郎
でも1組と2組の太郎は別人です。
このように、同じ名前であることによるコンフリクト(衝突)が起きないように「どこに属するメソッド、変数ですか?」というのを明記する仕組み
が名前空間です。
ここまでくるとわかってきたと思いますが、〇〇::△△
は〇〇に属する△△
という意味となります。
Device::ResistrationsController
はDeviseに属するResistrationsController
と読むことができます。
また、名前空間は「クラス」か「モジュール」単位で区分けをします
。
ここでは詳しい説明を省きますが、クラスとモジュールには次の違いがあります。
- クラス : 実体化できる (実体に固有の値やメソッドを定義できる)
- モジュール : 実体化できない
@scivola 様からご指摘をいただきました点について
下記で修正を加えています。
:: の意味 / 具体例
これまでの内容で、::
はA::B
の使い方をすることで、Aに属するBを呼び出す
という意味となることがわかりました。
もう少し詳しく見ると、::
には次の2つの意味合いがあります。
1. クラス・モジュールに属する定数の呼び出し
2. クラス・モジュールに属するメソッドの呼び出し
では、それぞれの例について見ていきましょう。
1. Mathモジュールの定数PIを参照する
Rubyの組み込みライブラリであるMathモジュールに属する定数PIを呼び出して、円周率を出力してみましょう。
(参照 : Rubyリファレンス | module Math)
puts Math::PI
このプログラムを実行します。
% ruby call_pi.rb
3.141592653589793
円周率π
を出力することができました。
定数を参照する場合はこのように使用します。
余談ですが、後の例に備えて、別な形での呼び出しを試してみます。
メソッドの呼び出しのように「.(ドット)」で呼び出してみます。
puts Math.PI
このプログラムを実行すると…
% ruby call_pi.rb
Traceback (most recent call last):
math.rb:1:in `<main>': undefined method `PI' for Math:Module (NoMethodError)
MathモジュールにPIというメソッドが定義されていません
というエラーです。
PIは定数 (値) であってメソッドではないのでこのようなエラーが出ると考えられます。
2. 動物クラス (自作) の「走る」メソッドを参照する
続いて「メソッド参照」の例を見てみましょう。
- いぬは4足で走る
- 人間は2足で走る
この例では名前空間があることの恩恵を知るために、まずは名前空間無しで書いてみましょう。
def run
puts '4足で走ります'
end
def run
puts '2足で走ります'
end
run
run
このプログラムを実行してみましょう。
% ruby run.rb
2足で走ります
2足で走ります
同じrun
というメソッド名を使い回すと、より後に定義されたメソッドが参照されます。
ではこれらのrun
をDog
Human
クラスで区切って定義してみましょう。
class Dog
def self.run
puts '4足で走ります'
end
end
class Human
def self.run
puts '2足で走ります'
end
end
Dog::run
Human::run
このプログラムを実行してみます。
% ruby run.rb
4足で走ります
2足で走ります
名前空間に沿ったメソッドが参照されました。
これはクラスを定義し、::
を使ったことで、Dogのrunを参照します
のように、レシーバを指定して呼び出せるようになったためです。
ちなみにこの::
の使い方 (メソッド呼び出し) の場合は、「.(ドット)」で代替することができます。
具体的には次の通りです。
(省略)
Dog.run
Human.run
% ruby run.rb
4足で走ります
2足で走ります
クラスメソッド呼び出しと同じ動作をする、ということがわかりました。
そして::
を「メソッド呼び出し」
として用いる場合は、クラスやモジュール以外もレシーバに指定することができます。
例えばこんな感じ。
10::times { |i| puts i }
% ruby sample.rb
0
1
2
3
4
5
6
7
8
9
以上が、::
の使い方と、その意味です。
まとめ
-
::
←これはメソッドや変数がどこに従属するかを示す記号 - 名前空間はメソッドや変数の利用範囲を指定する仕組み
- 名前空間はクラスやモジュールで区切る
Railsは便利な半面、自分でカスタマイズしようとするときは意外と苦労するなと感じています。
そしてその原因の大半はRubyの基礎を知らないこと
なのかなーと。
短い時間でキャッチアップすることも大事ですが、腰を据えて基本を理解するのも重要ですね。バランスをとりながら学習を進めようと思います。