Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

superは単に親クラスのメソッドを呼び出すものではない

はじめに

ruby gold取得に向けて勉強中superについて自分の中での理解が変わり共有したいと思いました。

本題

まず初めに以下のコードを実行するとどのような結果が出力されるでしょう?

module M
  def foo
    super
    puts "M#foo"
  end
end

class C2
  def foo
    puts "C2#foo"
  end
end

class C < C2
  def foo
    super
    puts "C#foo"
  end
  include M
end

C.new.foo

選択肢1

C2#foo
C#foo

選択肢2

C2#foo
M#foo
C#foo

選択肢3

エラーが表示される

僕はずっと1と思ってました。
ちなみに正解は 選択肢2
きちんと理解して正解した方はもうこれ以上見なくて大丈夫です。
ここまで見てくださってありがとうございます。

まず、僕がどのようにして選択肢1を選んだのか

「Cクラスのfooメソッドやな、ふむふむ」
「お、superか。てことは親クラスのfooを見ればいいんやな」
「なるほど、答えは1や!」

こんな感じです。
モジュールをincludeしたところで呼ばれないと思っていました。

superクラスについて学んでいきましょう。
まず初めにリファレンスマニュアルに書いてあるsuperについて簡単に

super は現在のメソッドがオーバーライドしているメソッドを呼び出します

なるほど、スーパークラスのメソッドを呼び出すわけではなさそうです。
ではancestorsメソッドを使用してみます。

## 省略

class C < C2
  def foo
    super
    puts "C#foo"
  end
  include M
  self.ancestors #=> [C, M, C2, Object, Kernel, BasicObject]
end

C.new.foo

ancestorsは簡単に説明するとメソッドの探索順位がわかるメソッドです。
例えばfooメソッドを実行した時Cのfooメソッドを探し、なければMのfoo...と探索していきます。

ここでもう一度問題のコードを見ていきます。

module M
  def foo
    super # C2のfooを参照する
    puts "M#foo"
  end
end

class C2
  def foo
    puts "C2#foo"
  end
end

class C < C2
  def foo
    super # Mのfooを参照する
    puts "C#foo"
  end
  include M
  self.ancestors #=> [C, M, C2, Object, Kernel, BasicObject]
end

C.new.foo
#=> C2#foo
#=> M#foo
#=> C#foo

結論

  • superの記述があると次のメソッドの探索が行われる
  • 親クラスのメソッドを探索するわけではない

おわりに

資格勉強していると結構理解が深まるので実務経験が浅い方は勉強してみてもいいのではないでしょうか?

nasuka
2020年4月から都内の受託会社で働いています。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away