継承とincludeおよび特異クラスによるRubyのメソッド探索順序
タグ: ruby / 初版公開: 2013-12-01

Ruby Method Traverse

継承とincludeおよび特異クラスが組み合わさった場合のRubyのメソッド探索順序は図中の番号のとおりだ。

Clazzはユーザが定義した親クラス、InheritClazzClazzを継承したクラス、InheritClazzModule1Module2をincludeする。 このクラス図ではincludeの結果、実際には現れない中間クラス(InheritClazz1)(InheritClazz2)が生成されることにしている。 さらにこのInheritClazzに特異メソッドmethodを定義した結果生成される特異クラスをSingletonInheritClazzとする。

文章で説明するとややこしくなってしまうが、ポイントを説明するとRubyでは以下1.から4.の順番でメソッドが探索され実行される。

  1. オブジェクトが特異クラスのインスタンスなら特異クラスで定義されたメソッドが呼ばれる
  2. クラスで定義したメソッドはincludeしたメソッドをオーバーライドする
  3. includeは後ろでインクルードしたModuleが前のModuleのメソッドをオーバーライドする
  4. 以上の条件に合致するメソッドがなければ継承元を再帰的に探索したメソッドが合致する

以下のコードと実行結果を見るとわかりやすい。 以下のコードでは、同名のメソッドが探索される順に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)
Rubyサポーターズ すがわら まさのり 寺田 玄太郎 三村 益隆 近藤 宇智朗 橋立 友宏 関口 亮一
技術評論社
売り上げランキング: 10,788