LoginSignup
0
0

More than 5 years have passed since last update.

Rubyでincludeを2回使った時のメソッド探索の順番を調べて見た

Posted at

includeextendについて調べていた時にこの記事の中でincludeを2回していた。
その時に2回includeするとメソッド探索の階層構造で上下関係はどうなるんだろうと思って調べて見た。

サンプルコード

sample.rb
def puts_safe
  puts yield
rescue => e
  puts "Error :< - #{e}"
end

class Neko
  class << self
    def class_method
      "class method in Neko"
    end
  end

  def instance_method
    "instance method in Neko"
  end
end

module Fur
  def m_method_for_color(color = "white")
    "module method: my fur is #{color} color."
  end

  def m_method_for_length(length = 2)
    "module method: my fur is #{length} cm."
  end

end

module Claw #つめ
  def m_method_for_color(color = "white")
    "module method: my claw is #{color} color."
  end
end

class Puma < Neko
  include Fur
  include Claw # ここを入れ替えたらどうなるのか気になった。

  def a_instance_method
    puts "a instance method in Puma"
  end
end

puts "<<pum1>>"

pum1 = Puma.new
puts_safe { pum1.m_method_for_color } #=>module method: my claw is white color.
puts_safe { pum1.m_method_for_length } #=>module method: my fur is 2 cm.

この例だと
Puma < Claw < Fur < Neko < Object < Kernel < BascObjectとなっていることがわかった。
実際にPuma.new.m_method_for_colorと`module Clawにもmodule Farにも書かれているメソッドを実行するとmodule Clawの方が実行された。

入れ替えてみる

includeの部分を入れ替えて見た。

sample.rb
def puts_safe
  puts yield
rescue => e
  puts "Error :< - #{e}"
end

class Neko
  class << self
    def class_method
      "class method in Neko"
    end
  end

  def instance_method
    "instance method in Neko"
  end
end

module Fur
  def m_method_for_color(color = "white")
    "module method: my fur is #{color} color."
  end

  def m_method_for_length(length = 2)
    "module method: my fur is #{length} cm."
  end

end

module Claw #つめ
  def m_method_for_color(color = "white")
    "module method: my claw is #{color} color."
  end
end

class Puma < Neko
+ include Claw
+ include Fur

  def a_instance_method
    puts "a instance method in Puma"
  end
end

puts "<<pum1>>"

pum1 = Puma.new
puts_safe { pum1.m_method_for_color } #=>module method: my fur is white color.
puts_safe { pum1.m_method_for_length } #=>module method: my fur is 2 cm.

前回の例では
Puma < Claw < Fur < Neko < Object < Kernel < BascObject
となっていたものが

今回の例では
Puma < Fur < Claw < Neko < Object < Kernel < BascObject

となっていた。

結論

includeすると愚直にクラスの階層1個上にmoduleを追加する。

class ClassC < classD
  include moduleA
  include moduleB
end

と記述があるとき、もちろん上から実行されるので
include moduleAが実行された時点では
class C < moduleA < classD < Object < Kernel < BasicObjectとなる。
次に下の行のinclude moduleBが実行されて
class C < moduleB < moduleA < classD < Object < Kernel < BasicObject
と階層構造が形成される。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0