Java でのオーバーライド

Java では、オーバーライドは、サブクラスまたは子クラスが、そのスーパークラスまたは親クラスの 1 つによってすでに提供されているメソッドの特定の実装を提供できるようにする機能です。サブクラスのメソッドがそのスーパークラスのメソッドと同じ名前、同じパラメータまたはシグネチャ、および同じ戻り値の型 (またはサブタイプ) を持つ場合、サブクラスのメソッドは次のようになります。 オーバーライド スーパークラスのメソッド。

メソッドのオーバーライドは、Java が次のことを実現する方法の 1 つです。 実行時のポリモーフィズム 。実行されるメソッドのバージョンは、そのメソッドの呼び出しに使用されるオブジェクトによって決まります。親クラスのオブジェクトを使用してメソッドを呼び出す場合は、親クラスのバージョンが実行されますが、サブクラスのオブジェクトを使用してメソッドを呼び出す場合は、子クラスのバージョンが実行されます。言い換えると、 それは参照されるオブジェクトのタイプです (参照変数の型ではありません) オーバーライドされたメソッドのどのバージョンが実行されるかを決定します。

Java でのメソッドのオーバーライドの例

以下は Java メソッド オーバーライドの実装です。

ジャワ




// Java program to demonstrate> // method overriding in java> // Base Class> class> Parent {> > void> show() { System.out.println(> 'Parent's show()'> ); }> }> // Inherited class> class> Child> extends> Parent {> > // This method overrides show() of Parent> > @Override> void> show()> > {> > System.out.println(> 'Child's show()'> );> > }> }> // Driver class> class> Main {> > public> static> void> main(String[] args)> > {> > // If a Parent type reference refers> > // to a Parent object, then Parent's> > // show is called> > Parent obj1 => new> Parent();> > obj1.show();> > // If a Parent type reference refers> > // to a Child object Child's show()> > // is called. This is called RUN TIME> > // POLYMORPHISM.> > Parent obj2 => new> Child();> > obj2.show();> > }> }>

出力

Parent's show() Child's show() 

Java メソッドのオーバーライドのルール

1. オーバーライドおよびアクセス修飾子

アクセス修飾子 オーバーライドするメソッドは、オーバーライドされたメソッドよりも多くのアクセスを許可できますが、それより少ないアクセスは許可されません。たとえば、スーパークラスの保護されたインスタンス メソッドは、サブクラスではパブリックにできますが、プライベートにはできません。そうするとコンパイル時エラーが発生します。

ジャワ




// A Simple Java program to demonstrate> // Overriding and Access-Modifiers> class> Parent {> > // private methods are not overridden> > private> void> m1()> > {> > System.out.println(> 'From parent m1()'> );> > }> > protected> void> m2()> > {> > System.out.println(> 'From parent m2()'> );> > }> }> class> Child> extends> Parent {> > // new m1() method> > // unique to Child class> > private> void> m1()> > {> > System.out.println(> 'From child m1()'> );> > }> > // overriding method> > // with more accessibility> > @Override> public> void> m2()> > {> > System.out.println(> 'From child m2()'> );> > }> }> // Driver class> class> Main {> > public> static> void> main(String[] args)> > {> > Parent obj1 => new> Parent();> > obj1.m2();> > Parent obj2 => new> Child();> > obj2.m2();> > }> }>

出力

From parent m2() From child m2() 

2. 最終メソッドはオーバーライドできません

メソッドをオーバーライドしたくない場合は、次のように宣言します。 最後の 。参照してください 継承を伴う Final の使用

ジャワ




// A Java program to demonstrate that> // final methods cannot be overridden> class> Parent {> > // Can't be overridden> > final> void> show() {}> }> class> Child> extends> Parent {> > // This would produce error> > void> show() {}> }>

出力

13: error: show() in Child cannot override show() in Parent  void show() { }  ^  overridden method is final 

3. 静的メソッドはオーバーライドできません (メソッドのオーバーライドとメソッドの非表示):

基本クラスの静的メソッドと同じシグネチャを持つ静的メソッドを定義すると、それは次のように呼ばれます。 メソッドの隠蔽 。次の表は、スーパークラスのメソッドと同じシグネチャを持つメソッドを定義した場合に何が起こるかをまとめたものです。

スーパークラスのインスタンスメソッド スーパークラスの静的メソッド
サブクラスのインスタンスメソッド オーバーライド コンパイル時にエラーが発生する
サブクラスの静的メソッド コンパイル時にエラーが発生する 隠す

ジャワ




// Java program to show that> // if the static method is redefined by> // a derived class, then it is not> // overriding, it is hiding> class> Parent {> > // Static method in base class> > // which will be hidden in subclass> > static> void> m1()> > {> > System.out.println(> 'From parent '> > +> 'static m1()'> );> > }> > // Non-static method which will> > // be overridden in derived class> > void> m2()> > {> > System.out.println(> > 'From parent '> > +> 'non - static(instance) m2() '> );> > }> }> class> Child> extends> Parent {> > // This method hides m1() in Parent> > static> void> m1()> > {> > System.out.println(> 'From child static m1()'> );> > }> > // This method overrides m2() in Parent> > @Override> public> void> m2()> > {> > System.out.println(> > 'From child '> > +> 'non - static(instance) m2() '> );> > }> }> // Driver class> class> Main {> > public> static> void> main(String[] args)> > {> > Parent obj1 => new> Child();> > // As per overriding rules this> > // should call to class Child static> > // overridden method. Since static> > // method can not be overridden, it> > // calls Parent's m1()> > obj1.m1();> > // Here overriding works> > // and Child's m2() is called> > obj1.m2();> > }> }>

出力

From parent static m1() From child non - static(instance) m2() 

4. プライベート メソッドはオーバーライドできません

プライベートメソッド コンパイル時に結合されるため、オーバーライドできません。したがって、サブクラス内のプライベート メソッドをオーバーライドすることさえできません。(「 これ 詳細については)。

ジャワ




class> SuperClass {> > private> void> privateMethod()> > {> > System.out.println(> > 'This is a private method in SuperClass'> );> > }> > public> void> publicMethod()> > {> > System.out.println(> > 'This is a public method in SuperClass'> );> > privateMethod();> > }> }> class> SubClass> extends> SuperClass {> > // This is a new method with the same name as the> > // private method in SuperClass> > private> void> privateMethod()> > {> > System.out.println(> > 'This is a private method in SubClass'> );> > }> > // This method overrides the public method in SuperClass> > public> void> publicMethod()> > {> > System.out.println(> > 'This is a public method in SubClass'> );> > privateMethod();> // calls the private method in> > // SubClass, not SuperClass> > }> }> public> class> Test {> > public> static> void> main(String[] args)> > {> > SuperClass obj1 => new> SuperClass();> > obj1.publicMethod();> // calls the public method in> > // SuperClass> > SubClass obj2 => new> SubClass();> > obj2.publicMethod();> // calls the overridden public> > // method in SubClass> > }> }>

出力

This is a public method in SuperClass This is a private method in SuperClass This is a public method in SubClass This is a private method in SubClass 

5. オーバーライドするメソッドは同じ戻り値の型 (またはサブタイプ) を持つ必要があります。

Java 5.0 以降では、子クラスのオーバーライド メソッドに異なる戻り値の型を持つことが可能ですが、子の戻り値の型は親の戻り値の型のサブタイプである必要があります。この現象はとして知られています 共変の戻り値の型

ジャワ




class> SuperClass {> > public> Object method()> > {> > System.out.println(> > 'This is the method in SuperClass'> );> > return> new> Object();> > }> }> class> SubClass> extends> SuperClass {> > public> String method()> > {> > System.out.println(> > 'This is the method in SubClass'> );> > return> 'Hello, World!'> ;> > }> }> public> class> Test {> > public> static> void> main(String[] args)> > {> > SuperClass obj1 => new> SuperClass();> > obj1.method();> > SubClass obj2 => new> SubClass();> > obj2.method();> > }> }>

出力

This is the method in SuperClass This is the method in SubClass 

6. サブクラスからオーバーライドされたメソッドを呼び出す

を使用して、オーバーライドするメソッドで親クラスのメソッドを呼び出すことができます。 スーパーキーワード

ジャワ




// A Java program to demonstrate that overridden> // method can be called from sub-class> // Base Class> class> Parent {> > void> show() { System.out.println(> 'Parent's show()'> ); }> }> // Inherited class> class> Child> extends> Parent {> > // This method overrides show() of Parent> > @Override> void> show()> > {> > super> .show();> > System.out.println(> 'Child's show()'> );> > }> }> // Driver class> class> Main {> > public> static> void> main(String[] args)> > {> > Parent obj => new> Child();> > obj.show();> > }> }>

出力

Parent's show() Child's show() 

オーバーライドとコンストラクター

親クラスと子クラスは同じ名前のコンストラクターを持つことができないため、コンストラクターをオーバーライドすることはできません (コンストラクター名は常にクラス名と同じである必要があります)。

オーバーライドと例外処理

以下に、例外処理に関連するメソッドをオーバーライドするときに注意すべき 2 つのルールを示します。

ルール #1

スーパークラスのオーバーライドされたメソッドが例外をスローしない場合、サブクラスのオーバーライド メソッドは例外をスローすることしかできません。 未チェックの例外 、チェック例外をスローすると、コンパイル時エラーが発生します。

ジャワ




// Java program to demonstrate overriding when> // superclass method does not declare an exception> class> Parent {> > void> m1() { System.out.println(> 'From parent m1()'> ); }> > void> m2() { System.out.println(> 'From parent m2()'> ); }> }> class> Child> extends> Parent {> > @Override> > // no issue while throwing unchecked exception> > void> m1()> throws> ArithmeticException> > {> > System.out.println(> 'From child m1()'> );> > }> > @Override> > // compile-time error> > // issue while throwing checked exception> > void> m2()> throws> Exception> > {> > System.out.println(> 'From child m2'> );> > }> }>

出力

error: m2() in Child cannot override m2() in Parent  void m2() throws Exception{ System.out.println('From child m2');}  ^  overridden method does not throw Exception 

ルール #2

スーパークラスのオーバーライドされたメソッドが例外をスローする場合、サブクラスのオーバーライド メソッドは同じサブクラスの例外のみをスローできます。で親例外をスローする 例外階層 コンパイル時エラーが発生します。また、サブクラスのオーバーライドされたメソッドが例外をスローしていなければ問題はありません。

ジャワ




// Java program to demonstrate overriding when> // superclass method does declare an exception> class> Parent {> > void> m1()> throws> RuntimeException> > {> > System.out.println(> 'From parent m1()'> );> > }> }> class> Child1> extends> Parent {> > @Override> > // no issue while throwing same exception> > void> m1()> throws> RuntimeException> > {> > System.out.println(> 'From child1 m1()'> );> > }> }> class> Child2> extends> Parent {> > @Override> > // no issue while throwing subclass exception> > void> m1()> throws> ArithmeticException> > {> > System.out.println(> 'From child2 m1()'> );> > }> }> class> Child3> extends> Parent {> > @Override> > // no issue while not throwing any exception> > void> m1()> > {> > System.out.println(> 'From child3 m1()'> );> > }> }> class> Child4> extends> Parent {> > @Override> > // compile-time error> > // issue while throwing parent exception> > void> m1()> throws> Exception> > {> > System.out.println(> 'From child4 m1()'> );> > }> }>

出力

error: m1() in Child4 cannot override m1() in Parent  void m1() throws Exception  ^  overridden method does not throw Exception 

オーバーライドおよび抽象メソッド

インターフェイスまたは抽象クラスの抽象メソッドは、派生具体クラスでオーバーライドされるように設計されています。オーバーライドされない場合、コンパイル時エラーがスローされます。

オーバーライドおよび Synchronized/strictfp メソッド

メソッドに synchronized/strictfp 修飾子が存在しても、オーバーライドのルールには影響しません。つまり、synchronized/strictfp メソッドが非 synchronized/strictfp メソッドをオーバーライドしたり、その逆が可能である可能性があります。

注記:

  1. C++ では、次のことが必要です。 仮想キーワード オーバーライドを実現するか、 実行時のポリモーフィズム 。 Java では、メソッドはデフォルトで仮想です。
  2. マルチレベルのメソッドオーバーライドを行うことができます。

ジャワ




// A Java program to demonstrate> // multi-level overriding> // Base Class> class> Parent {> > void> show() { System.out.println(> 'Parent's show()'> ); }> }> // Inherited class> class> Child> extends> Parent {> > // This method overrides show() of Parent> > void> show() { System.out.println(> 'Child's show()'> ); }> }> // Inherited class> class> GrandChild> extends> Child {> > // This method overrides show() of Parent> > void> show()> > {> > System.out.println(> 'GrandChild's show()'> );> > }> }> // Driver class> class> Main {> > public> static> void> main(String[] args)> > {> > Parent obj1 => new> GrandChild();> > obj1.show();> > }> }>

出力

GrandChild's show() 

メソッドのオーバーライドとメソッドのオーバーロード

1. 過負荷 ほぼ同じメソッドですが、シグネチャが異なります。オーバーライドはほぼ同じメソッド、同じシグネチャですが、継承を通じて接続された異なるクラスです。

2. オーバーロードはコンパイラ時のポリモーフィズムの一例であり、オーバーライドは実行時のポリモーフィズムの一例です 多態性

Java メソッドのオーバーライドに関する FAQ

Q1.メソッドのオーバーライドとは何ですか?

前述したように、オーバーライドされたメソッドにより Java はサポートできるようになります。 実行時のポリモーフィズム 。ポリモーフィズムがオブジェクト指向プログラミングに不可欠である理由は 1 つあります。ポリモーフィズムにより、一般クラスがその派生クラスのすべてに共通するメソッドを指定できるようになり、サブクラスがそれらのメソッドの一部またはすべての特定の実装を定義できるようになります。オーバーライドされたメソッドは、Java がポリモーフィズムの 1 つのインターフェイス、複数のメソッドの側面を実装するもう 1 つの方法です。 動的メソッドディスパッチ これは、オブジェクト指向設計がコードの再利用と堅牢性を実現する最も強力なメカニズムの 1 つです。クリーンな抽象インターフェイスを維持しながら、再コンパイルせずに新しいクラスのインスタンスのメソッドを呼び出す既存のコード ライブラリの機能は、非常に強力なツールです。オーバーライドされたメソッドを使用すると、派生クラス オブジェクトの型を知らなくても、任意の派生クラスのメソッドを呼び出すことができます。

Q2.メソッドのオーバーライドをいつ適用するか? (例付き)

オーバーライドと 継承 : ポリモーフィズムをうまく適用するための鍵の 1 つは、スーパークラスとサブクラスが、より低い専門化からより大きな専門化に移行する階層を形成していることを理解することです。正しく使用すると、スーパークラスは、サブクラスが直接使用できるすべての要素を提供します。また、派生クラスが独自に実装する必要があるメソッドも定義します。これにより、サブクラスはそのメソッドを柔軟に定義できるようになりますが、それでも一貫したインターフェイスが強制されます。 したがって、継承とオーバーライドされたメソッドを組み合わせることで、スーパークラスは、そのすべてのサブクラスで使用されるメソッドの一般的な形式を定義できます。 メソッドのオーバーライドを使用した、より実践的な例を見てみましょう。組織の従業員管理ソフトウェアを考えてみましょう。コードには単純な基本クラス Employee があり、そのクラスには raiseSalary()、transfer()、promote() などのメソッドがあります。マネージャー、エンジニア、エンジニアなど、さまざまな種類の従業員が存在します。 ..etc には、基本クラス Employee に存在するメソッドの実装がある場合があります。私たちの完全なソフトウェアでは、従業員の種類を知らなくても、どこにでも従業員のリストを渡し、適切なメソッドを呼び出すだけで済みます。たとえば、従業員のリストを反復処理することで、すべての従業員の給与を簡単に引き上げることができます。すべてのタイプの従業員のクラスに独自のロジックが含まれている可能性がありますが、特定のタイプの従業員に raiseSalary() が存在する場合は、そのメソッドのみが呼び出されるため、心配する必要はありません。

ジャワ




// Java program to demonstrate application> // of overriding in Java> // Base Class> class> Employee {> > public> static> int> base => 10000> ;> > int> salary() {> return> base; }> }> // Inherited class> class> Manager> extends> Employee {> > // This method overrides salary() of Parent> > int> salary() {> return> base +> 20000> ; }> }> // Inherited class> class> Clerk> extends> Employee {> > // This method overrides salary() of Parent> > int> salary() {> return> base +> 10000> ; }> }> // Driver class> class> Main {> > // This method can be used to print the salary of> > // any type of employee using base class reference> > static> void> printSalary(Employee e)> > {> > System.out.println(e.salary());> > }> > public> static> void> main(String[] args)> > {> > Employee obj1 => new> Manager();> > // We could also get type of employee using> > // one more overridden method.loke getType()> > System.out.print(> 'Manager's salary : '> );> > printSalary(obj1);> > Employee obj2 => new> Clerk();> > System.out.print(> 'Clerk's salary : '> );> > printSalary(obj2);> > }> }>

出力

Manager's salary : 30000 Clerk's salary : 20000 

関連記事

  • Java における動的メソッド ディスパッチまたはランタイム ポリモーフィズム
  • オブジェクトクラスのequals()メソッドをオーバーライドする
  • Object クラスの toString() メソッドをオーバーライドする
  • Javaでのオーバーロード
  • Java プログラムの出力 |セット 18 (オーバーライド)