Rubyのsuperがやってくれること

2022.06.02

superについての理解をまとめていく。effective ruby 項目7

superとは?

super は現在のメソッドがオーバーライドしているメソッドを呼び出します。括弧と引数が省略された場合には現在のメソッドの引数がそのまま引き渡されます。引数を渡さずにオーバーライドしたメソッドを呼び出すには super() と括弧を明示します。

Ruby リファレンス3.1マニュアル

クラスを継承した際に継承元と同じメソッドを使いたい場合にsuperを使う。superの呼び出し方は括弧や引数の書き方によってメソッドの呼ばれ方が変わるみたい。

基本的な使い方

継承元(スーパークラス)と同じメソッドを呼び出して実行する。superの方が先に実行される。

class Animal
 def bark
   puts "鳴き声"
 end

 def a
   "a"
 end
end

class Dog < Animal
 def bark
   super
   puts "わんわん"
 end

 def habitat
   super
   puts "陸"
 end

 def a
   result = super
   puts result
 end
end

dog = Dog.new
dog.bark
<<< 鳴き声 
<<< わんわん

dog.habitat
<<< `habitat': super: no superclass method `habitat' for #<Dog:0x00007f8a2d00e010> (NoMethodError)

dog.a
<<< a

継承元クラスに存在しないhabitatメソッドを呼び出すとNoMethodErrorになる。aメソッドのように処理結果をもらうこともできる。

括弧と引数の書き方

オーバーライドメソッドの呼び出し方によって挙動が変わる場合がある。

class Animal
 def age(x)
   puts "#{x}歳です"
 end
end

class Dog < Animal
 def age(x)
   super(x)
   super x
   super
   super(x + 1)
   super()  
 end
end

dog = Dog.new
dog.age(4)
<<< 4 
<<< 4
<<< 4
<<< 5
<<<`age': wrong number of arguments (given 0, expected 1) (ArgumentError)

superのみだと引数が渡されるが、super()で引数無し括弧だと引数が渡されずArgumentErrorが出ることに注意。

どんな場合に使える?

親クラスと子クラスがあり、子クラスで親クラスのメソッドを呼び出したい時。

共通の処理を基底クラスを用意して他のクラスでオーバーライドメソッドを呼び出すことでそれぞれ別の処理を進められる。