35
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Last updated at Posted at 2020-11-07

概要

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

::←これです。

  • Devise::RegistrationsController
  • ActiveHash::Base
  • ActiveRecord::Migrationなど

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

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


::←これの正体

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

名前空間とは?

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

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

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

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

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

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

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


:: の意味 / 具体例

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

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

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

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


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

Rubyの組み込みライブラリであるMathモジュールに属する定数PIを呼び出して、円周率を出力してみましょう。
(参照 : Rubyリファレンス | module Math)

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は定数 (値) であってメソッドではないのでこのようなエラーが出ると考えられます。


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

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

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

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

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

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

run
run

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

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

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

ではこれらのrunDog 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

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


まとめ

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

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

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


参照

35
23
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
35
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?