名前空間
名前空間は定数に修飾をつけて一位になるようにするための手段である。最も基本的なレベルでは名前空間は定数を定義するための新しいスコープを作れる。
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クラスで定義されている定数(トップレベル定数)を参照するには::が使える。
そして名前空間を扱うときはレキシカルスコープを意識する。
ユーザーのロール分けなどで名前空間を使うと同じ名前でメソッドを書けるようになる。