親クラスのメソッドを呼び出す際に使用されるsuper
には、super
、super()
、super(*)
、super(**)
など、いくつかの異なる呼び方があります。
この記事では、それぞれの呼び方の違いと具体的な使用例について説明します。
これで僕みたいにとりあえずsuper
って書いておけば良いんでしょって人が減ると嬉しいですね。
super
super
は、現在のメソッドに渡された引数をそのまま親クラスのメソッドに渡します。
class Person
def initialize(name, age)
@name = name
@age = age
end
end
class Yuusha < Person
def initialize(name, age)
super
end
end
yuusha = Yuusha.new('tarou', 28)
親クラスのメソッドが、現在のメソッドと同じ引数を必要とする場合に使用します。コードがシンプルで読みやすくなるため、最も一般的な使用方法です。
ただし、親クラスと子クラスで引数の数が違うとエラーが発生します。
class Person
def initialize(name, age)
@name = name
@age = age
end
end
class Yuusha < Person
def initialize(name, age, hp)
super
end
end
yuusha = Yuusha.new('tarou', 28, 60)
# => index.rb:2:in `initialize': wrong number of arguments (given 3, expected 2) (ArgumentError)
super()
super()
は、引数なしで親クラスのメソッドを呼び出します。
class Person
def initialize
puts 'Personの初期化'
end
end
class Yuusha < Person
def initialize(name, age)
@name = name
@age = age
super()
end
end
yuusha = Yuusha.new('tarou', 28)
# => Personの初期化
親クラスのメソッドが引数を必要としない場合に使用します。現在のメソッドが引数を受け取っていても、親クラスのメソッドには渡したくない場合に便利です。
super(*)
super(*)
は、スプラット演算子(*)を使用して引数を展開することで、親クラスのメソッドに全ての引数を配列として渡します。
class Person
def initialize(*args)
puts "この人の装備は#{args.join('、')}"
end
end
class Yuusha < Person
def initialize(*args)
super(*args)
end
end
yuusha = Yuusha.new('天空のつるぎ', '天空の鎧', '天空の兜')
yuusha = Yuusha.new('天空のつるぎ', '天空の鎧', '天空の兜', '天空の盾')
# => この人の装備は天空のつるぎ、天空の鎧、天空の兜
# => この人の装備は天空のつるぎ、天空の鎧、天空の兜、天空の盾
現在のメソッドが可変長引数を受け取り、それを親クラスのメソッドへそのまま渡す場合に使用します。引数の数や内容が動的に決まる場合に有効です。
super(**)
super(*)
は、スプラット演算子(**)を使用して引数を展開することで、親クラスのメソッドに全ての引数をハッシュオブジェクトとして渡します。
class Person
def initialize(**args)
args.each do |key, value|
instance_variable_set("@#{key}", value)
end
end
end
class Yuusha < Person
def initialize(**args)
super(**args)
end
end
yuusha = Yuusha.new(name: 'tarou', age: 28, hp: 100)
puts yuusha.instance_variable_get('@name')
puts yuusha.instance_variable_get('@age')
puts yuusha.instance_variable_get('@hp')
# => tarou
# => 28
# => 100
yuusha2 = Yuusha.new(name: 'zirou', age: 25, hp: 100, mp: 200)
puts yuusha2.instance_variable_get('@name')
puts yuusha2.instance_variable_get('@age')
puts yuusha2.instance_variable_get('@hp')
puts yuusha2.instance_variable_get('@mp')
# => zirou
# => 25
# => 100
# => 200
spuer(*)と同様、引数の数や内容が動的に決まる場合に有効です。例のように、キーと値の形でインスタンス変数を動的に設定することも可能です。
super(arg1, arg2, ...)
super
を使うときに、具体的な引数を直接渡すこともできます。
class Person
def initialize(name ,age)
@name = name
@age = age
end
end
class Yuusha < Person
def initialize(name, age, hp)
@hp = hp
super(name.upcase, age)
end
end
yuusha = Yuusha.new('tarou', 28, 100)
puts yuusha.instance_variable_get('@name')
puts yuusha.instance_variable_get('@age')
puts yuusha.instance_variable_get('@hp')
# => TAROU
# => 28
# => 100
現在のメソッドが受け取った引数と異なる引数を親クラスのメソッドに渡したい場合に使用します。引数を加工してから渡す場合に便利です。
まとめ
- super: 引数をそのまま親クラスに渡す
- super(): 引数なしで親クラスのメソッドを呼び出す
- super(*): 可変長引数をフラットに展開して親クラスに配列として渡す
- super(**): 可変長引数をフラットに展開して親クラスにハッシュオブジェクトとして渡す
- 直接引数を指定: 特定の引数を親クラスに渡す
これらの方法を使い分けることで、Rubyのメソッド継承をより柔軟にコントロールできます。ぜひsuper
を使う時はどれを使うと一番効率よく継承をコントロールできるのか考えてみてください。