Edited at

モジュール内のメソッドにsuperを書いた場合と書かなかった場合の違い

More than 3 years have passed since last update.

モジュール内でsuperが書かれている時にエラーが出たり出なかったりするので試してみた。


①モジュール内のメソッドにsuperが書かれていないケース。

クラスAのfooメソッド内のsuperで、includeしているモジュールの同名メソッドが呼ばれてる。

module M

def foo
puts "モジュールM#foo"
end
end

class A
include M
def foo
super
puts "クラスA#foo"
end
end

p A.ancestors
A.new.foo


結果

[A, M, Object, Kernel, BasicObject]

モジュールM#foo
クラスA#foo


②モジュール内のメソッドにsuperを書いたケース。(エラー発生)

①と違いは、モジュールMのfooメソッドにsuperが書かれてるとこ。

クラスAインスタンスの継承関係でモジュールMのsuperclassが存在しないのでエラーが出てるみたい。

module M

def foo
super
puts "モジュールM#foo"
end
end

class A
include M
def foo
super
puts "クラスA#foo"
end
end

p A.ancestors
A.new.foo


結果

[A, M, Object, Kernel, BasicObject]

sample_module_super.rb:3:in `foo': super: no superclass method `foo' for #<A:0x007fd9921fd790> (NoMethodError)
from sample_module_super.rb:11:in `foo'
from sample_module_super.rb:17:in `<main>'



③ モジュール内のメソッドにsuperを書いて、別途クラスを追加したケース。

②との違いはクラスBを定義して、クラスAにクラスBを継承させた。

クラスAインスタンスについての継承関係だと、モジュールBのsuperがクラスBになっている。

class B

def foo
puts "クラスB#foo"
end
end

module M
def foo
super
puts "モジュールM#foo"
end
end

class A < B
include M
def foo
super
puts "クラスA#foo"
end
end

p A.ancestors
A.new.foo


結果

[A, M, B, Object, Kernel, BasicObject]

クラスB#foo
モジュールM#foo
クラスA#foo


④ 別途クラスを追加して、モジュール内のメソッドのsuperは消したケース。

③と違いは、モジュールMのfooメソッドのsuperを消したとこ。

class B

def foo
puts "クラスB#foo"
end
end

module M
def foo
puts "モジュールM#foo"
end
end

class A < B
include M
def foo
super
puts "クラスA#foo"
end
end

p A.ancestors
A.new.foo


結果

[A, M, B, Object, Kernel, BasicObject]

モジュールM#foo
クラスA#foo


感想

モジュール内のメソッドにsuperを書くとエラーが出る可能性があるのでよろしくない気がする。


参考サイト


[Ruby]やったーRuby技術者認定Gold受かったよー\(^o^)/

http://d.hatena.ne.jp/rightgo09_ruby/20121226/p1

「superはincludeされてるモジュールは呼ばれる?」


superclassでは出てこないから、呼ばれないと思ってたけど…。


module M

def hoge
puts "module M"
super
end
end

class Hoge
def hoge
puts "class Hoge"
end
end

class Fuga < Hoge
include M
def hoge
puts "class Fuga"
super
end
end

Fuga.new.hoge


結果

class Fuga

module M
class Hoge


げげ呼ばれた…。モジュールもsuperの対象になるのか…。この辺で3問くらいミスった気がするな。