モジュールとクラスと名前空間
名前空間の話。入門的なサイトだと全く解説されてなかったりするけど、手元のスクリプト以上になれば必須だよねー。
- モジュール/クラスの内部で定義された内部モジュール/内部クラスを外部から参照したい場合、「::」で参照する。
- 内部モジュール/内部クラスのメソッドを外部から書き換えたい場合、外側のクラス/モジュールを定義しなおして書き換える。直接は書き換えられない。
- モジュールメソッド/クラスメソッドは、自身の内部で定義する場合、"def self.foo"で定義できる。
- 内部から"def Foo.foo"と定義するのと基本的には同じ。だが、自身のモジュール/クラス名と同じ名前の内部モジュール/クラス名が既に定義されていた場合、"def Foo.foo"は"Foo::Foo.foo"として定義されるので要注意。
- つまり、実行時点の状態によって名前空間が微妙にずれる場合があるってことか。
- 普段は"def self.foo"で内部から定義すべきだろね。
- でも、これ使ってキモイことも出来そう。かな。
- 内部から"def Foo.foo"と定義するのと基本的には同じ。だが、自身のモジュール/クラス名と同じ名前の内部モジュール/クラス名が既に定義されていた場合、"def Foo.foo"は"Foo::Foo.foo"として定義されるので要注意。
以下、自分用メモ。
#一通り定義してみる module Foo def self.foo # 「def Foo.foo」と同義 puts "Foo.foo is called" end class Bar def self.bar # 「def Bar.bar」と同義 puts "Foo::Bar.bar is called" end end end class Bar def self.bar puts "Bar.bar is called" end class InnerBar end end #確かめる Foo.foo # => Foo.foo is called Foo::Bar.bar #=> Foo::Bar.bar is called Bar.bar # => Bar.bar is called #Barクラスのbarメソッドを書き換える def Bar.bar puts "Bar.bar is rewrited" end #Barクラスの内部クラスInnerBarクラスにメソッドを追加する #「def Bar::InnerBar.bar」とは書けない。 class Bar def InnerBar.bar puts "Bar::InnerBar.bar is called" end end Bar.bar # => Bar.bar is rewrited Bar::InnerBar.bar # => "Bar::InnerBar.bar is called" #Fooモジュールのfooメソッドを書き換える def Foo.foo puts "Foo.foo is rewrited" end Foo.foo # => Foo.foo is rewrited #Foo::Barクラスのbarメソッドを書き換えたい場合、 #「def Foo::Bar.bar」とは書けない。 #そのモジュールを再定義し、必要な部分だけを追記する。 module Foo def Bar.bar puts "Foo::Bar.bar is rewrited" end end Foo::Bar.bar #=> Foo::Bar.bar is rewrited #Fooモジュールに内部モジュールを定義してみる module Foo module InnerFoo def self.foo puts "Foo::InnerFoo.foo is called" end end end Foo::InnerFoo.foo # => Foo.foo is rewrited Foo.foo # => Foo.foo is rewrited :当然、Fooモジュールのメソッドとは区別される #Barクラスに内部モジュールを定義してみる class Bar module InnerModule def self.bar puts "Bar::InnerModule.bar is called" end end end Bar::InnerModule.bar # => Bar::InnerModule.bar is called