継承とincludeおよび特異クラスが組み合わさった場合のRubyのメソッド探索順序は図中の番号のとおりだ。
Clazz
はユーザが定義した親クラス、InheritClazz
はClazz
を継承したクラス、InheritClazz
はModule1
とModule2
をincludeする。 このクラス図ではincludeの結果、実際には現れない中間クラス(InheritClazz1)
と(InheritClazz2)
が生成されることにしている。 さらにこのInheritClazz
に特異メソッドmethod
を定義した結果生成される特異クラスをSingletonInheritClazz
とする。
文章で説明するとややこしくなってしまうが、ポイントを説明するとRubyでは以下1.から4.の順番でメソッドが探索され実行される。
- オブジェクトが特異クラスのインスタンスなら特異クラスで定義されたメソッドが呼ばれる
- クラスで定義したメソッドはincludeしたメソッドをオーバーライドする
- includeは後ろでインクルードしたModuleが前のModuleのメソッドをオーバーライドする
- 以上の条件に合致するメソッドがなければ継承元を再帰的に探索したメソッドが合致する
以下のコードと実行結果を見るとわかりやすい。 以下のコードでは、同名のメソッドが探索される順にputs
で番号を出力した後、super
で上位のメソッドを呼び出している。結果として標準出力には1から5が順に出力される。
# 親クラス
class Clazz
def method
puts '5'
end
end
# モジュール1
module Module1
def method
puts '4'
super
end
end
# モジュール2
module Module2
def method
puts '3'
super
end
end
# InheritClazzはClazzを継承しModule1とModule2をインクルードする
class InheritClazz < Clazz
include Module1
include Module2
def method
puts '2'
super
end
end
# InheritClazzのインスタンス生成
object = InheritClazz.new
# 特異メソッド定義
def object.method
puts '1'
super
end
object.method
1
2
3
4
5
メソッドの探索順序については、パーフェクトRubyの6-4が詳しい。
パーフェクトRuby (PERFECT SERIES 6)
posted with amazlet at 13.12.01
Rubyサポーターズ すがわら まさのり 寺田 玄太郎 三村 益隆 近藤 宇智朗 橋立 友宏 関口 亮一
技術評論社
売り上げランキング: 10,788
技術評論社
売り上げランキング: 10,788