Rubyでメソッドを呼び出すことをメソッドの探索やメソッド名の解決と言いますが、Rubyはこれらをどの様に処理しているか簡単にまとめてみようと思います、初学者向け。
obj
というオブジェクトがあったとして、obj.m
というメソッド呼び出しがあった場合、Rubyは以下の優先順位でメソッドの探索を行います。
- objの特異メソッド
- objのクラスのmというインスタンスメソッド
- objのクラスがインクルードしているモジュールのインスタンスメソッド(includeされた順とは逆順でモジュールを検索する)
- スーパークラスのインスタンスメソッド
- スーパークラスがインクルードしているモジュールのインスタンスメソッド
- 見つからない場合、
method_missing
メソッドが呼び出される
特異メソッドやらインスタンスメソッドなど色々出てきたのでそれぞれについて簡単に説明します。
#特異メソッド(singleton method)
特異メソッドとは、特定のオブジェクト固有のメソッドです。
obj = "object" # Stringクラスのオブジェクト
def obj.hello # objの特異メソッド
puts "hello " + self
end
obj.hello # => "hello object"
obj2 = "object2"
obj2.hello # helloはobjの特異メソッドなのでobj2では使えません
obj2では、undefined method `hello'とエラーを吐いてしまいます。
#インスタンスメソッド
その名の通りインスタンスオブジェクト(Hoge.new
してできるやつ)から呼び出せるメソッドです。
class Greeting
def hello # Greetingクラスのインスタンスメソッド
puts "hello"
end
end
obj = Greeting.new
obj.hello # => "hello"
Greeting.hello # これはGreetingクラスのクラスメソッドです、エラーを吐きます
急に出てきたクラスメソッドというやつはクラスオブジェクトが持つメソッドで、この例で使おうとするとGreetingクラス内でdef self.hello
の様に定義してGreeting.hello
という様に使います、インスタンスを生成していない所に注意してください。
#インクルードされたモジュールのインスタンスメソッド
Rubyでは、include Hoge
と書くことで、Hogeモジュールが他の所でも使える様になります。
モジュールとはメソッド等をまとめることができるもので、オブジェクトが作成できないクラスの様な感じです。
module Greeting
def hello
puts "hello"
end
end
class NoHello
include Greeting # Greetingモジュールをインクルード
end
obj = NoHello.new
obj.hello # => "hello"
この様に、helloメソッドを実装していないクラスのインスタンスからhelloメソッドを呼び出すことができます。
#スーパークラスのインスタンスメソッド
Rubyでは、スーパークラスを継承してサブクラスを作成することで、スーパークラスのメソッドを呼び出すことができます。
Rubyは純粋なオブジェクト指向の言語なので、全てのクラスはObjectというスーパークラスのサブクラスです。
class Super # スーパークラス
def hello # スーパークラスのインスタンスメソッド
puts "hello"
end
end
class Sub < Super # Superクラスを継承してサブクラスを作成
end
obj = Sub.new
obj.hello # => "hello"
obj2 = Super.new
obj2.hello # もちろんこれも"hello"です
スーパークラスがインクルードしているモジュールのインスタンスメソッドというのは、Super
の中でインクルードした場合を考えればわかると思います。
#missing_method
missing_method
は、メソッドを探索してどこにも見つからなかった場合に最終的に呼び出されるメソッドです。
呼び出されるとNoMethodError
を出します。
obj = "object"
obj.no # => "undefined method `no' for "object":String (NoMethodError)"
ちなみにRubyは、メソッド探索に成功するとキャッシングするので同じメソッドをその後検索するときは高速に処理される様になります。
#参考文献
プログラミング言語 Ruby