プログラムを再利用する際に非常に便利な”オーバーライド”ですが、初心者の方にとっては若干理解しにくい部分もあるのではないでしょうか?
そこで今回はこのオーバーライドについて出来るだけわかりやすい例えも含めながら解説してみたいと思います。
慣れてくると非常に便利だと実感できるものですので、これを機に学習してみましょう!
オーバーライドとは
クラスの中身を若干変えて再利用したいのですが、作り替えなければダメでしょうか?
オーバーライドという方法を使えば作り替えることなく再利用できます。
「スーパークラス内のメソッドをサブクラスで再利用すること」オーバーライドと言います。
一言でいうなら、「クラス継承時に同じようなメソッドを使い回せる便利機能」と思っていただいても良いでしょう。
またスーパークラスという言葉がありますが、これは特に難しく考える必要はなく、継承関係でいうと親クラスという意味で捉えてください。
「スーパークラス=親」、「サブクラス=子ども」という認識で大丈夫です。
オーバーライドのメリット
一番のメリットは記述量を減らすことが出来ます。
また変更が必要な場合も、変更すべき部分が少なくなります。
オーバーライドされたクラスはメンバ変数をそのまま利用でき、変更したい場合も該当するメソッドのみ再定義できるからです。
オーバーライドの使い方
サンプルコードを見ながら解説をしていきます。
次のコードを見てください。
class ClassSuper { protected int i1 = 3; protected int i2 = 5; public void calc(){ System.out.println("i1 + i2 = " + (i1 + i2)); } } class ClassSub extends ClassSuper{ @Override public void calc(){ System.out.println("i1 * i2 = " + (i1 * i2)); } } public class OverrideSample { public static void main(String[] args) { ClassSub cs = new ClassSub(); cs.calc(); } }
実行結果
i1 * i2 = 15
このコードでは、”extends”を使ってサブクラス(子クラス)である”ClassSub”がスーパークラス(親クラス)の”ClassSuper”を継承しています。
また継承と同時にサブクラス内でオーバーライドして”calc”に対しメソッドの再定義をしていることが分かります。
“@Override”で使用されている「@」はアノテーションと言います。
オーバーライドさせる場合に必要となる宣言だと思ってください。
実行結果を見てみると、オーバーライドさせたことによりcalcが再定義され計算式は変更されていますが、メンバ変数はサブクラス内で記述していないにもかかわらずスーパークラスのメンバ変数が適用されていることが確認できます。
superについて
サブクラスでオーバーライドした場合にも、スーパークラスと同じ処理をしたいケースもあります。
そういった場合には”super”を使うことで再定義後でも元のメソッドをそのまま実行できます。
次のコードを見てください。
class ClassSuper { protected int i1 = 3; protected int i2 = 5; public void calc(){ System.out.println("i1 + i2 = " + (i1 + i2)); } } class ClassSub extends ClassSuper{ @Override public void calc(){ System.out.println("i1 * i2 = " + (i1 * i2)); // 追加処理(super句) super.calc(); } } public class OverrideSample { public static void main(String[] args) { ClassSub cs = new ClassSub(); cs.calc(); } }
実行結果
i1 * i2 = 15 i1 + i2 = 8
今回のコードは一連の流れとして、まずスーパークラスである”ClassSuper”をサブクラスである”ClassSub”が継承し、クラス内でオーバーライドしてメソッド”calc”を再定義するという部分までは先ほどのコードと全く変わりありません。
但し今回はこの後、追加で「super.calc();」という記述を施しています。
順当に考えれば、この”calc”メソッドは既にオーバーライドして再定義しているので、その内容である式が出力される際には変更後の内容が出力されますが、”super”句が付与されているため、メインメソッドで実行した際には元のメソッドで定義されている「System.out.println(“i1 + i2 = ” + (i1 + i2));」がそのまま出力されます。
実行結果を見てみると、サブクラスで”calc”を再定義したにもかかわらず元のメソッドとして呼び出されていることが確認できます。
オーバーライド規則
オーバーライドの利便性についてはここまでの説明で理解していただけたと思いますが、このオーバーライドには使用上の注意もいくつか存在します。
よって、ここからはオーバーライドの注意点について解説していきたいと思います。
継承したものしかオーバーライド出来ない
ここまでの説明で既にお気づきだと思いますが、オーバーライドする為には、元になるクラスを参照させる必要が有ります。
よって、”extends”を使用し元となるクラスを継承していないものに関してはオーバーライドすることはできません。
但し再継承でサブクラスを継承させる場合には、元となるサブクラスが既にスーパークラスを継承しているため、この限りではありません。
戻り値と引数について
オーバーライドさせるメソッドについては命名の変更は禁止となっています。
例えば、スーパークラス内のメソッドが”sampleMethod”の場合、サブクラス内でも同じ名前にする必要があります。
これはメンバ変数に対しても同じです。
また引数の数や順番も変更することはできません。
static修飾子とfinal修飾子について
オーバーライドは再定義を目的としているため、staticの様な静的修飾子で括られているものは使用不可となっています。
また”final”修飾子の基本定義は変更不可修飾子という位置付けのため、いかなる場合もオーバーライド出来ません。
修飾子の誓約
オーバーライドさせるメソッドはスーパークラス側のアクセスレベルより上のレベル設定が不可能となっています。
例えばスーパークラス側で”protected”修飾子で括られたメソッドに対し、サブクラス側で”private”に変更することはできません。
また”abstract”が宣言されている場合には、使用の有無に関わらずサブクラスでは必ずオーバーライドしなければならないというルールが存在します。
これをしないまま使用すると、オーバーライドしたクラス全体にabstractが付与されます。
まとめ
いかがでしたか?
今回はオーバーライドについて解説をしてみました。
開発において継承自体は非常によく利用するものとなっていますので、継承とオーバーライドはセットで覚えておくと良いと思います。
オーバーライド自体もロジックはそこまで難しいものではありませんので、”super”の適用範囲などを色々試して確認しておくと更に深く理解できるようになると思います。