4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[Ruby]同名のメソッドを持つ複数の Module を include してメソッドを呼ぶと?

Last updated at Posted at 2019-05-10

概要

同名のメソッドを持つ複数の Module を include した場合、メソッドを呼び出したときにどういう動きをするんだろう?という疑問が唐突に頭を過ぎりました。本当に唐突ですみません。

最初は事例やドキュメントを探してみようかと思ったのですが、これなら実際やってみたほうが早いと思いましたので簡単なサンプルコード書いて確認してみました。結果を以下に記載していきたいと思います。

予想

  1. include でコケる
  2. メソッドの呼び出しでコケる
  3. 最後に include された Module に実装されたメソッドの動きになる

3っぽい気はします。

環境

ruby 2.5.1

結論

選択肢3 が正解でした。後勝ち みたいですね。 include の順番を入れ替えたら出力結果が変わることも確認できました。

検証用サンプルコード

適当な Module を3つ用意し、全てのモジュールに run メソッドを実装しました。これを全て include して run を実行したときにどのような動きをするかを確認する、というかんじで使いました。
そもそも Module の設計とかメソッドの名前とかに問題があるんじゃね?と言われたらぐうの音も出ないのでひとまずここではスルーしてくださいw

test.rb
# module
module ModA
  def run
    p :ModA
  end
end

module ModB
  def run
    p :ModB
  end
end

module ModC
  def run
    p :ModC
  end
end

# class
class Sample
  include ModA
  include ModB
  include ModC
end

# main
Sample.new.run # => "ModC"

追記

@Nabetani さんから、さらに充実した検証コードを下記コメントでご教示いただきました。感謝。
https://qiita.com/tommy_aka_jps/items/f02732d993a726574f83#comment-761cc0f00cb95cc869b1

※環境によってはアンカーリンクがうまく機能していないようなので、前述のコメントからコードを転載します。

module ModA
  def run; p :ModA ;end
end

module ModB
  def run; p :ModB ;end
end

module ModC
  def run; p :ModC ;end
end

module ModD
  def run; p :ModD ;end
end

class UseInclude
  include ModA
  def run; p :UseInclude; end
end

UseInclude.new.run #=> :UseInclude

class UsePrepend
  prepend ModA
  def run; p :UsePrepend; end
end

UsePrepend.new.run #=> :ModA

o = UsePrepend.new

def o.run; p :"o.run"; end
o.run #=> :"o.run"

o.class.prepend ModB

o.run #=> :"o.run"

o.singleton_class.include ModC

o.run #=> :"o.run"

o.singleton_class.prepend ModD

o.run #=> :ModD

おわりに

よく考えてみればそんなに意外な結果ではないですかね。仮に Sample クラスで run メソッドをオーバーライドしたら当然そっちで動きますしね。 Module って C# で言うところの interface みたいなイメージを持っていたので、メソッド呼び出しの際に型指定がないとエラーになるかと勘違いしていました。クラスの多重継承を扱える言語はまだ触ったことがないので他の言語だとどうなんでしょうね。C++ とか詳しい方、よろしければご教示ください。(他力本願)

4
1
8

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
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?