LoginSignup
11
12

More than 5 years have passed since last update.

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

Last updated at Posted at 2015-01-18

モジュール内で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問くらいミスった気がするな。

11
12
1

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
11
12