今回はmodule外のクラスを呼び出したい場合の対処法についてまとめました。タイトルで全て完結している感がありますが、例を踏まえながらみていきます。
【事象】予期しないクラスが呼び出される
以下のようなUserクラスがあり、その中にinitializeメソッドが定義されると仮定します。この場合、User.new
を実行すると「module外のinitialize」が出力されます。
# sample.rb
class User
def initialize
puts 'module外のinitialize'
end
end
User.new
% ruby sample.rb
=> module外のinitialize
続いて、同名のクラス名を持ち一方がmoduleで囲まれているとします。では、そのmodule内でUser.new
を実行するとどうなるのでしょうか。
# sample.rb
class User
def initialize
puts 'module外のinitialize'
end
end
module Admin
class User
def initialize
puts 'module内のinitialize'
end
end
User.new
end
この場合はmodule内のinitializeメソッドが実行され、「module内のinitialize」が出力されるようになります。次の項目では、このような場合にmodule外のinitializeメソッドを呼び出す方法についてみていきます。
% ruby sample.rb
=> module内のinitialize
【解決策】::(コロン2つ)を付ける
クラス名の始めに::(コロン2つ)を付けることで、module外のクラスを呼び出すことができます。先程の例では、User.new
を::User.new
にすることで解決できます。
class User
def initialize
puts 'module外のinitialize'
end
end
module Admin
class User
def initialize
puts 'module内のinitialize'
end
end
::User.new
end
% ruby sample.rb
=> module外のinitialize
このように::(コロン2つ)は、モジュールやクラス内で定義された定数名を外部から参照するときに使用されます。
まとめ
- 同名のクラス名を持ち一方がmoduleで囲まれ、module内でクラスを呼び出した場合、module内のクラスが呼び出される
- クラス名の始めに::(コロン2つ)を付けることで、module外のクラスを呼び出すことができる
参考
ころんころんの話をしよう。もしくはモジュールの名前空間について。
今回はmodule外のクラスを呼び出したい場合の対処法についてまとめました。クラスを呼び出す際に想定した挙動にならない場合は、今回の事象を疑ってみても良いかもしれません。