概要
原著者の許諾を得て翻訳・公開いたします。
- 英語記事: The super keyword – Mehdi Farsi – Medium
- 原文公開日: 2018/05/16
- 著者: Mehdi Farsi
- サイト: http://ruby.devscoop.fr/ Ruby/Railsのニュースレター「DevScoop-Ruby」を発行するフランスのサイトです。
日本語タイトルは内容に即しました
Ruby: super
キーワードの4つの側面(翻訳)
私の発行するRuby 💌ニュースレター💌はこちらです!ご自由にサブスクライブいただけます!🚀
本記事では以下のトピックについて扱います。
- 暗黙の引数
super
vssuper()
- ブロック付き
super
- ancestorsチェイン付き
super
暗黙の引数
引数を使うメソッドが、子クラスのどれかにあるメソッドによってオーバーライドされている状態で、その子クラス内でsuper
を引数なしで呼び出すと、子クラスのメソッドの引数が自動的に親クラスのメソッドに渡されます。
次の例をちょっとご覧ください。
class Parent
def say(message)
puts message
end
end
class Child < Parent
def say(message)
super
end
end
irb> Child.new.say('Hi!')
#=> Hi!
Child
クラスはParent
クラスを継承し、このChild
クラスはParent#say
メソッドをオーバーライドしています。
Child#say
メソッド内では、super
に引数を渡さずに呼び出しています。
すなわち、Rubyは#say
メソッドの探索をChild
クラスの「ancestorsチェイン」内で行い、見つかったメソッドにmessage
引数を渡します。
メモ: Rubyのancestorsチェインのメカニズムについて知りたい方は私の別記事もどうぞ。
しかし、ここでParent#say
メソッドが引数をまったく取らないとしたらどうでしょうか。
super
vs super()
先ほどのParent#say
メソッドを再定義して、message
引数を取っ払ってみましょう。
class Parent
def say
puts "親です"
end
end
class Child < Parent
def say(message)
super
end
end
irb> Child.new.say('Hi!')
#=> ArgumentError (wrong number of arguments (given 1, expected 0))
Parent#say
メソッドが引数を受け取らないにもかかわらず、Child#say
でsuper
を呼んだためにChild#say
メソッドのmessage
引数が暗黙でParent#say
メソッドに渡されてしまいました。
この問題を回避するには、Child#say
メソッドに渡される引数を受け取らないようsuper
に明示的に指示を出す必要があります。
そのためには、super
キーワードに丸かっこを追加して、super()
とします。
class Parent
def say
puts "親です"
end
end
class Child < Parent
def say(message)
super()
end
end
irb> Child.new.say('Hi!')
#=> 親です
お次は、Parent#say
メソッドにブロックを1つ渡してみましょう。
ブロック付きsuper
Parent#say
メソッドを再定義して、yield
キーワードを追加しましょう。
class Parent
def say
yield
end
end
class Child < Parent
def say
super
end
end
irb> Child.new.say { puts 'よかった!ママかパパだ' }
#=> よかった!ママかパパだ
Child.new.say
メソッド呼び出しに渡されたブロックは、super
キーワードを経由して、Parent#say
メソッドに暗黙で渡されます。
お次はyield
キーワードでこのブロックをキャッチし、Parent#say
メソッド内で実行してみましょう。
メモ: yield
について知りたい方は私の別記事もどうぞ。
ancestorsチェイン付きsuper
#say
メソッドが定義されているGrandParent
クラスをParent
クラスに継承しましょう。
class GrandParent
def say(message)
puts "おじいちゃんかおばあちゃん: #{message}"
end
end
class Parent < GrandParent
end
class Child < Parent
def say(message)
super
end
end
irb> Child.new.say('Hi!')
#=> おじいちゃんかおばあちゃん: Hi!
ここでのsuper
キーワードは、#say
メソッドの探索をParent
クラス内で試みます。
Parent
クラスにはこのメソッドが定義されていないため、super
は続いてParent
クラスのスーパークラス内(つまりGrandParent
クラス)でメソッド探索を試みます。
GrandParent
クラスには#say
メソッドが定義されています。
これで、Child.new.say
メソッド呼び出しに渡された'Hi!'
引数は、super
キーワードを経由してGrandParent#say
メソッドに暗黙で渡されます。
いかがでしたか?
本記事をお読みいただきありがとうございました😊。
本記事がお役に立ちましたら、ぜひMedium.comの元記事で存分に👏ボタンを押してください。
前回の私の記事『Method Arguments in Ruby: Part II – Mehdi Farsi – Medium』もどうぞ。