rubyの名前空間

2022.07.25

名前空間

名前空間は定数に修飾をつけて一位になるようにするための手段である。最も基本的なレベルでは名前空間は定数を定義するための新しいスコープを作れる。

Effective Ruby

スコープを新しく作って定数同士の衝突を防いでくれる。

特徴

名前空間を使うときはプロジェクトのディレクトリ構造に合わせて書くのが普通。

今回の場合だとbooディレクトリにあるarray.rbファイルになる。呼び出しのBoo::Arrayはboo/array.rbを指している。

名前空間内にクラスを作るための代わりの構文もある。ただし名前空間を定義していないとエラーになる。

module Boo
  class Array
  end
end

↓

class Boo::Array # メインファイルでモジュールを読み込むことで可能。(実践してない)
end

rubyのコアライブラリにあるクラスたとえばArrayとかはミュータブルなのでメソッドを追加、削除できる。

名前空間を使わずに自前のArrayクラスを定義してしまうと既存のArrayクラスを書き換えることになってしまう。

自前定義のArrayクラスの中でコアライブラリのArrayを使用したい場合。::を使用する。既存のArrayクラスに影響を与えずに自前のArrayクラスを定義したい時。

module Boo
  class Array
    def a
      arr = Array.new
      p arr
    end

    def b
      arr = ::Array.new
      p arr
    end
  end
end
tmp = Boo::Array.new
tmp.a #=> #<Boo::Array:0x00007f8aa897a678>
tmp.b #=> []

レキシカルスコープ

定数が定義されたり参照した時のネストの位置関係。呼び出せたり呼び出せなかったりすること。

module Boo
  KEY = "harro"
  class A
    def initialize(key = KEY)
      p key
    end
  end
end
Boo::A.new #=> "harro"

一見呼び出せそうだが、KEYを呼び出せない。

module Boo
  KEY = "harro"
end

class Boo::A
  def initialize(key = KEY)
    p key
  end
end
Boo::A.new #=> uninitialized constant Boo::A::KEY (NameError)

定数KEYの呼び出し方を変更する

module Boo
  KEY = "harro"
end

class Boo::A
  def initialize(key = Boo::KEY)
    p key
  end
end
Boo::A.new #=> "harro"

まとめ

名前空間の構造はでディレクトリ構造と同じようにする。Objectクラスで定義されている定数(トップレベル定数)を参照するには::が使える。

そして名前空間を扱うときはレキシカルスコープを意識する。

ユーザーのロール分けなどで名前空間を使うと同じ名前でメソッドを書けるようになる。