はじめに
言語の基本的な動作を確認する作業って、ついサボってしまうことが多いのですが、今回は職場の先輩に時間を頂いて
あらためてRubyで多重継承に伴うメソッドの呼び出され方を検証しました。
Rubyはクラスの多重継承ができない言語ですが、Moduleを用いて事実上の多重継承を可能にしています(Mixin方式)
ケース1:複数のModuleを継承
module Foo
def do_task
puts "I'm in Foo class!"
end
end
module Bar
def do_task
puts "I'm in Bar class!"
end
end
class Child
include Foo
include Bar
def execute
do_task
end
end
instance = Child.new
instance.execute # which task is called?
結果:後勝ち
$ ruby case1.rb
I'm in Bar class!
ケース2:親クラス継承+Module取り込み
module Foo
def do_task
puts "I'm in Foo class!"
end
end
module Bar
def do_task
puts "I'm in Bar class!"
end
end
class Parent
def do_task
puts "I'm in the Parent class!"
end
end
class Child < Parent
include Foo
include Bar
def execute1
do_task
end
def do_task
super
end
end
instance = Child.new
instance.execute1 # which task is called?
instance.do_task # which task is called?
結果:取り込むModuleの後勝ち
$ ruby case2.rb
I'm in Bar class!
I'm in Bar class!
ケース3:菱形継承(ダイヤモンド継承)
module Parent
def do_task
puts "I'm in the Parent class!"
end
end
module Foo
include Parent
end
module Bar
include Parent
end
class Child
include Foo
include Bar
def execute
do_task
end
end
instance = Child.new
instance.execute # which task is called?
結果:問題なく実行可能
$ ruby case3.rb
I'm in the Parent class!
まとめ
というわけで、Rubyではダイヤモンド継承にまつわる問題も回避できていること、基本的には後に書かれたものがオーバーライドするという挙動を確認しました。
複雑なコードでは随所に継承やModuleの取り込みを行いますので、このような基本的コードで挙動を検証するのもたまにはいいかもしれませんね。
多重継承については、Wikipediaでも一定量の知識を習得できるので、CSバックグラウンドがない方やエンジニアになりたての方はあらためて確認してみても良いかもしれません