スポンサーリンク
継承する方法
Rubyの継承は、「<」を使用する。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class Human def eat puts "ご飯を食べた" end end class Programmer < Human def work puts "コードを書いた" end end programmer = Programmer.new programmer.eat #=> "ご飯を食べた" |
プログラマーも人間なので、ご飯を食べることが出来る。
スポンサーリンク
オーバーライド
オーバーライドとは、親クラスで定義しているメソッドと同名のメソッドを子クラスで普通に再定義(上書き)すること。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | class Human def eat puts "ご飯を食べた" end end class Programmer < Human def work puts "コードを書いた" end def eat puts "急いでご飯を食べた" end end programmer = Programmer.new programmer.eat #=> 急いでご飯を食べた |
プログラマーである以上、ご飯は急いで食べなければならない。
親クラスのメソッドを呼ぶ方法
オーバーライドの定義域内で、superを使うことで、親クラス定義されている同名のメソッドを呼ぶことが出来る。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class Human def sleep puts "寝た" end end class Programmer < Human def sleep super puts "しかし何故かぐっすり眠れない" end end programmer = Programmer.new programmer.sleep #実行結果 #寝た #しかし何故かぐっすり眠れない |
何か悩みでもあるのか、プログラマーはぐっすり眠れない。
superに引数を渡す
superに引数を渡すことも出来るが、ちょっとややこしい。
まず、superはデフォルトで引数を全部勝手に引き継ぐ。どういうことかと言うと、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class Foo def plus_5 num=0 puts num + 5 end end class Bar < Foo def plus_5 num super num super end end bar = Bar.new bar.plus_5 3 #実行結果 #8 #8 |
Barクラスのオーバーライド定義域においてsuperで親のメソッドを呼んでいるのだが、受け取った引数をsuperに渡そうが渡すまいが、plus_5メソッドが受け取った3という引数が親メソッドに渡されているのが分かる。
つまり、superで親クラスのメソッドを呼ぶ際、わざわざ引数を渡さなくてもよい。
親クラスのplus_5メソッドの引数にデフォルト値を設定してみる。↓
1 2 3 4 5 6 7 8 9 10 11 | class Foo def plus_5 num=0 puts num + 5 end end class Bar < Foo def plus_5 super end end |
この状態で、子クラスのplus_5メソッドを引数なしで呼んでみると、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class Foo def plus_5 num=0 puts num + 5 end end class Bar < Foo def plus_5 super end end bar = Bar.new bar.plus_5 #=> 5 |
親クラスのデフォルト値である0が引数として使われているのが分かる。
ややこしいのは、子クラスで別のデフォルト値を設定した場合。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class Foo def plus_5 num=0 puts num + 5 end end class Bar < Foo def plus_5 num=10 super end end bar = Bar.new bar.plus_5 #=> 15 |
この場合、子クラスで設定したデフォルト値10がsuperに渡される。つまり子クラスのデフォルト値が優先される。
子クラスで設定したデフォルト値をスルーしてsuperを呼ぶ方法もある。superにあえて空の()を付ける。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class Foo def plus_5 num=0 puts num + 5 end end class Bar < Foo def plus_5 num=10 super super() end end bar = Bar.new bar.plus_5 #実行結果 #15 #5 |
super()の方は出力結果が5になっているように、子クラスのデフォルト値が無視されて親クラスのデフォルト値が使われているのが分かる。
実は、superに空の()を付けて使うと、そもそもplus_5メソッドが受け取った引数を無効化されることになる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class Foo def plus_5 num=0 puts num + 5 end end class Bar < Foo def plus_5 num=10 super super() end end bar = Bar.new bar.plus_5 20 #実行結果 #25 #5 |
とりあえず以下のことを頭に入れておくとよいと思う。
- superはメソッドが受け取った引数(あるいは子クラスで定義したデフォルト値)を自動的に親クラスのメソッドに渡して呼ぶ
- 純粋に親クラスで定義したメソッドを呼びたい場合はsuper()を使う
superclassメソッド
全てのクラスは、クラスメソッドとしてsuperclassメソッドを持っている。
superclassメソッドは、そのクラスの親クラス名を返す。
1 2 3 4 5 6 7 8 9 10 11 12 13 | class Human def eat puts "ご飯を食べた" end end class Programmer < Human def work puts "コードを書いた" end end p Programmer.superclass #=>Human |
プログラマーも人間であることが分かる。
あくまでクラスメソッドであり、インスタンスに対して使ってもエラーになるだけなので注意。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class Human def eat puts "ご飯を食べた" end end class Programmer < Human def work puts "コードを書いた" end end programmer = Programmer.new p programmer.superclass #=> error |
is_a?メソッド
上記のsuperclassメソッドはクラスメソッドだが、インスタンスメソッドでis_a?メソッドというのもある。
is_a?メソッドは引数にクラスオブジェクトを受け取り、レシーバが引数のクラスの子孫にあたるクラスのインスタンスならtrueを返す。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class Human def eat puts "ご飯を食べた" end end class Programmer < Human def work puts "コードを書いた" end end programmer = Programmer.new p programmer.is_a? Human #=> true |
やはりプログラマーも人間であることが分かる。
一番かんたんなJava入門ではお世話になりました。
なんかみたことある書き方だなと思ったら、Nobuoさんでしたw
Rubyでもわかりやすい記事ありがとうございます!
by ナカムラカズキ 2018年10月9日 7:10 PM
>ナカムラさん
なかなかのマニアですね。笑
ありがとうございます!
by Nobuo@管理人 2018年10月9日 9:57 PM
[…] Ruby の継承とオーバーライドについてまとめてみた | Java からの Ruby on Rails 入門 […]
by 継承 [Ruby] – Site-Builder.wiki 2019年1月11日 6:10 AM