【Java】オーバーライド(Override)とは?使い方について解説!
オーバーライド(Override)とは「メソッドの継承」のことであり、一度別のクラスで定義したメソッドを上書きすることが可能となります。
メソッドを継承することで、別のクラスでの再利用が可能となり、書く記述量を減らすことができます。
また、変更が必要になった場合に、変更する箇所を少なくすることもでき、修正が楽になります。
今回はオーバーライド(Override)の使い方について解説していきます。
目次
オーバーライド(Override)とは
オーバーライドとは「メソッドの継承」のことをいいます。
フィールドとは異なり、メソッドの場合はその変数の型ではなく、インスタンスの実体の型によって決されます。
オーバーライド(Override)の書き方
オーバーライドの構文は下記となります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
class A { void sampleA() { 処理内容A } } class B extends A { public static void main(String[] args) { @Override void sampleA() { 処理内容B } } } |
別びクラスで同じメソッドを定義していますが、extends使ってクラスを継承し、オーバーライドをすることでsampleAメソッドを処理内容Aから処理内容Bに上書きすることができます。
また、「@Override」はアノテーションと呼ばれており、これを記述することでもし、スーパークラスに同名のメソッドがなかった場合にエラーメッセージを表示するようになります。
必須ではありませんが、つけておくと良いでしょう。
オーバーロードとの違い
オーバーロードとは同じメソッド名で、引数の数や順番が違うメソッドを定義することですが、それに比べてオーバーライドは継承したサブクラスで同じメソッド名で、引数の数や順番が同じメソッドを再び定義するものとなります。
オーバーロードについてはこちらをご参考ください。
オーバーライドを行ったサンプルコード
オーバーライドを行ったサンプルコードを紹介します。
Parent.java
1 2 3 4 5 6 7 8 9 10 |
// 親クラス public class Parent { String name = "親クラス"; void hello() { System.out.println("ParentClass:私は" + this.name + "です。"); } } |
Child.java
1 2 3 4 5 6 7 8 9 10 11 |
// 子クラス public class Child extends Parent { String name = "子クラス"; @Override void hello() { System.out.println("ChildClass:私は" + this.name + "です"); } } |
Main.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
// 孫クラス public class Main extends Child { String name = "メインクラス"; @Override void hello() { System.out.println("MainCalss: 私は" + this.name + "です。"); } public static void main(String[] args) throws Exception { Main main1 = new Main(); Child child = main1; Parent parent = main1; main1.hello(); child.hello(); parent.hello(); } } |
出力結果
MainCalss: 私はメインクラスです。
MainCalss: 私はメインクラスです。
MainCalss: 私はメインクラスです。
オーバーライドによってメソッドの内容が上書きされました。
フィールドと異なり、スーパークラス型での変数で実行しても実行結果は同じになります。
オーバーライドの条件
メソッドのオーバーライドは、次の条件があります。
① 同じメソッド名 であること
② 戻り値型が同じ であること
またはスーパークラスのメソッドの戻り値型のクラスのサブクラスであること
またはスーパークラスのメソッドの戻り値がインタフェースであればその実装クラスであること
③ 仮引数の数、型が同じ であること
④ スローする例外の型が同じ であること
または、そのサブクラスの例外 であること
⑤ アクセス指定子が同じであること
または、より緩いアクセス指定子であること
したがって、次のgetValueメソッドを下記のコードのようにオーバーライドすると、コンパイルエラーになります。
元になるメソッド
1 2 3 4 5 6 7 8 |
// オーバーライド元となるメソッド protected Integer getValue(List list) throws IOException { return null; } |
パラメータの型が異なる場合
1 2 3 4 5 6 7 8 9 |
// パラメータの型が異なる @Override protected Integer getValue(ArrayList list) throws IOException { return null; } |
アクセス指定子がより厳しくなった場合
1 2 3 4 5 6 7 8 9 |
// アクセス指定子がprotectedから // パッケージプライベートに(より厳しく)なった @Override Integer getValue(List list) throws IOException { return null; } |
例外のスーパークラスになっている場合
1 2 3 4 5 6 7 8 9 10 |
//スローする例外が元のメソッドがスローする //例外のスーパークラスになっている @Override protected Integer getValue(List list) throws Exception { return null; } |
パラメータの数が異なる場合
1 2 3 4 5 6 7 8 9 10 11 12 |
// パラメータの数が異なる // アノテーションがなければオーバーロードとみなされ、 // コンパイルできるようになる @Override protected Integer getValue(List list, String str) throws IOException { return null; } |
オーバーライドをしたつもりが、パラメータの数を変えただけのオーバーロードしたメソッドだったということを防ぐためにも、「@Override」アノテーションを付けるようにしてください。
staticメソッドを継承したときの注意点
Main.javaを実行したとき、その変数の型に限らず、「hello」メソッドの実行結果は同じでした。
しかし、static宣言したメソッドを使うと、実行結果は異なります。
Parent.java
1 2 3 4 5 6 7 8 9 10 |
// 親クラス public class Parent { static String name = "親クラス"; static void hello() { System.out.println("ParentClass:私は" + this.name + "です。"); } } |
Child.java
1 2 3 4 5 6 7 8 9 10 |
// 子クラス public class Child extends Parent { static String name = "子クラス"; static void hello() { System.out.println("ChildClass:私は" + this.name + "です"); } } |
Main.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
// 孫クラス public class Main extends Child { static String name = "孫"; static void hello() { System.out.println("Grandchild: 私は" + this.name + "です。"); } public static void main(String[] args) throws Exception { Main main1 = new Main(); Child child = main1 Parent parent = main1 main1.hello(); child.hello(); parent.hello(); } } |
出力結果
MainClass: 私はでメインクラスです。
ChildClass: 私は子クラスです。
ParentClass: 私は親クラスです。
これは、static宣言したメソッドはクラスに紐付くためです。
メソッド呼び出し時のパラメータの参照渡しで意図しない結果になることが多いので、staticメソッドを呼び出すときはインスタンスを使わずにクラスを使って呼び出すようにしてください。
1 2 |
Child.hello(); // Childクラスのhelloメソッドを呼び出す Parent.hello(); // Parentクラスのhelloメソッドを呼び出す |
staticメソッドの継承はオーバーライドではなく、隠蔽になるので「@Override」アノテーションを付けることはできません。
今日のポイント
オーバーライド(Override)でメソッドを継承する
⚫︎ オーバーライドするにはextendsを使用し、オーバーライドを行うとメソッドを継承することができる
⚫︎ オーバーライドとは継承元のメソッドを継承先のメソッドの内容に上書きするイメージである
⚫︎ オーバーライドを行うには複数の条件がある
⚫︎ staticメソッドをオーバーライドする場合、クラスから直接呼び出す必要がある
ST
株式会社flyhawkのSTです。フライテックメディア事業部でのメディア運営・ライター業務なども担当。愛機はMac Book AirとThinkPad。好きな言語:swift、JS系(Node.js等)。好きなサーバー:AWS。受託開発やプログラミングスクールの運営をしております。ご気軽にお問い合わせください。