ホーム DoRuby super の話

super の話

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

こんにちは、bibioです。ruby には super というオーバーライドしているメソッドを呼び出す機能があります。

何気なく使うとはまることがあるので違いを区別します。

説明した通り、superはオーバーライドしているメソッドを呼び出す機能です。

class A
  def foo
    puts "A#foo"
  end
end

class B < A
  def foo
    super
    puts "B#bar"
  end
end

のとき、次のように出力されます。

B.new.foo 
=>
A#foo
B#bar

では、以下のような例だとどうでしょうか?

class A
  def foo
    puts "A#foo"
  end
end

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

class B < A
  include M
  def foo
    super
    puts "B#bar"
  end
end

突然ですが、問題です。 B.new.foo() を実行したときに出力されるのは次のうちどれでしょうか?

(1)

M#bar

A#bar

B#bar

(2)

A#bar

B#bar

(3)

M#bar

B#bar

正解は・・・(3)

super はオーバーライドをするメソッドを呼び出すのであって、常に親クラスのメソッドを呼び出すわけではありません。名前に引きずられそうですね。

何もMix-inされていない場合、オーバーライドする親クラスのメソッドが呼び出されます。(なければ、その親クラスの親)といって、どれにもマッチしなければ method_missing が呼ばれます。通常は、NoMethodError になります。

オーバーライドされたメソッド呼び出しの階層を注意します。

include でモジュールをMix-inした場合は、元のクラスの上位に割り込みます。

メソッドの探索順にいえば、A->M->B になります。

メソッドの階層は ancestorsメソッドを使って調べます。上の例だと次の通り(Ruby2.1.xの場合)

irb> B.ancestors
=> [B, M, A, Object, Kernel, BasicObject]
記事を共有

最近人気な記事