Java でのオーバーライド
サブクラスが、その親クラスですでに定義されているメソッドに特定の実装を提供する場合、それはメソッドのオーバーライドと呼ばれます。サブクラスのオーバーライドされたメソッドは、親クラスのメソッドと同じ名前パラメータと戻り値の型を持たなければなりません。
メソッドオーバーライドのルール
- 名前パラメータと戻り値の型は親メソッドと一致する必要があります。
- Java は、参照変数の型だけでなく実際のオブジェクトの型に基づいて、実行時に実行するメソッドを選択します。
- 静的メソッドはオーバーライドできません。
- の @オーバーライドアノテーション メソッド名のタイプミスなどの間違いを見つけます。
class Animal { void move (){ System . out . println ( 'Animal is moving.' ); } void eat (){ System . out . println ( 'Animal is eating.' ); } } class Dog extends Animal { @Override void move (){ // move method from Base class is overriden in this // method System . out . println ( 'Dog is running.' ); } void bark (){ System . out . println ( 'Dog is barking.' ); } } public class Geeks { public static void main ( String [] args ) { Dog d = new Dog (); d . move (); d . eat (); d . bark (); } }
出力
Dog is running. Animal is eating. Dog is barking.
説明: Animal クラスは、次のような基本機能を定義します。 動く() そして 食べる() 。 Dog クラスは Animal と オーバーライド 特定の動作を提供する move() メソッド 犬が走っています。 どちらのクラスも独自のメソッドにアクセスできます。 Dog オブジェクトを作成するときに move() を呼び出すと、オーバーライドされたメソッドが実行されます。
オーバーライドにおける特殊なケース
1. superを使用した親メソッドの呼び出し
の スーパーキーワード オーバーライドするメソッドから親クラスのメソッドを呼び出すことができます。
Java class Parent { void show (){ System . out . println ( 'Parent's show()' ); } } class Child extends Parent { @Override void show (){ super . show (); System . out . println ( 'Child's show()' ); } } public class Main { public static void main ( String [] args ){ Parent obj = new Child (); obj . show (); } }
出力
Parent's show() Child's show()
2. Final メソッドはオーバーライドできません
メソッドをオーバーライドしたくない場合は、次のように宣言します。 ファイナル 。ご覧ください 継承を伴う Final の使用 。
Java class Parent { // Can't be overridden final void show (){ } } class Child extends Parent { // This would produce error void show () {} }
出力 :
3. 静的メソッド
- 静的メソッドはオーバーライドできません。スーパークラスと同じシグネチャを持つ静的メソッドをサブクラスで定義すると、スーパークラスのメソッドが非表示になります。
- インスタンス メソッドはオーバーライドできますが、サブクラスはスーパークラスの静的メソッドをオーバーライドできません。
- スーパークラスの静的メソッドと同じシグネチャを持つサブクラスの静的メソッドは、元のメソッドを隠します。
class Parent { static void staticMethod (){ System . out . println ( 'Parent static method' ); } void instanceMethod (){ System . out . println ( 'Parent instance method' ); } } class Child extends Parent { static void staticMethod (){ // Hides Parent's static method System . out . println ( 'Child static method' ); } @Override void instanceMethod (){ // Overrides Parent's instance method System . out . println ( 'Child instance method' ); } } public class GFG { public static void main ( String [] args ){ Parent p = new Child (); // Calls Parent's static method (hiding) p . staticMethod (); // Calls Child's overridden instance method p . instanceMethod (); } }
出力
Parent static method Child instance method
4. プライベートメソッド
- プライベート メソッドはサブクラスからは認識されないため、オーバーライドできません。
- 同名のサブクラスメソッドは、親クラスとは関係のない新たな独立メソッドとして扱われます。
class Parent { private void display (){ System . out . println ( 'Parent private method' ); } } class Child extends Parent { void display (){ // This is a new method not overriding System . out . println ( 'Child method' ); } } public class GFG { public static void main ( String [] args ){ Child c = new Child (); // Calls Child's method c . display (); } }
出力
Child method
5. 共変の戻り値の型
- メソッドのオーバーライドでは、オーバーライドするメソッドの戻り値の型を、オーバーライドされるメソッドの戻り値の型のサブクラスにすることができます。
- この機能は共変の戻り値の型として知られており、サブクラスでより具体的な戻り値の型を許可します。
class Parent { Parent getObject (){ System . out . println ( 'Parent object' ); return new Parent (); } } class Child extends Parent { @Override // Covariant return type Child getObject () { System . out . println ( 'Child object' ); return new Child (); } } public class GFG { public static void main ( String [] args ){ Parent obj = new Child (); // Calls Child's method obj . getObject (); } }
出力
Child object
オーバーライド時の例外処理
- オーバーライドするメソッドは、新しい例外や、スーパークラスのメソッドよりも広範囲のチェック例外をスローできません。
- スローされるチェック例外の数が減ったり、範囲が狭くなったりする可能性があります。
- スーパークラスのメソッドに関係なく、未チェックの例外 (RuntimeException など) をスローする可能性があります。
import java.io.IOException ; class Parent { void display () throws IOException { System . out . println ( 'Parent method' ); } } class Child extends Parent { @Override void display () throws IOException { System . out . println ( 'Child method' ); } } public class GFG { public static void main ( String [] args ){ // Parent reference Child object Parent obj = new Child (); try { // Calls Child's overridden method obj . display (); } catch ( IOException e ){ System . out . println ( 'Exception caught: ' + e . getMessage ()); } } }
出力
Child method
なぜメソッドのオーバーライドを使用するのでしょうか?
- サブクラス内の既存のメソッドの動作を変更または強化すること。
- 実行時のポリモーフィズムを実現するには、メソッド呼び出しは実際のオブジェクトの種類に依存します。
- メソッド名を論理的に再利用して冗長性を削減します。
実際の例: 従業員管理システム
現実世界の例えでオーバーライドを理解してみましょう。
組織の従業員管理システムを想像してください。すべての従業員は、raiseSalary() や Promotion() などの一部の動作を共有しますが、ロジックはマネージャーやエンジニアなどの役割によって異なります。個々の従業員が異なるタイプ (販売技術者など) である単一の Employee 配列を作成し、その関数を呼び出すことができます。これにより、コード全体が大幅に簡素化されます。
Java abstract class Employee { abstract void raiseSalary (); abstract void promote (); } class Manager extends Employee { @Override void raiseSalary (){ System . out . println ( 'Manager salary raised with incentives.' ); } @Override void promote (){ System . out . println ( 'Manager promoted to Senior Manager.' ); } } class Engineer extends Employee { @Override void raiseSalary (){ System . out . println ( 'Engineer salary raised with bonus.' ); } @Override void promote (){ System . out . println ( 'Engineer promoted to Senior Engineer.' ); } } public class Company { public static void main ( String [] args ){ Employee [] employees = { new Manager () new Engineer () }; System . out . println ( '--- Raising Salaries ---' ); for ( Employee e : employees ){ e . raiseSalary (); } System . out . println ( 'n--- Promotions ---' ); for ( Employee e : employees ) { e . promote (); } } }
出力
--- Raising Salaries --- Manager salary raised with incentives. Engineer salary raised with bonus. --- Promotions --- Manager promoted to Senior Manager. Engineer promoted to Senior Engineer.
説明: Manager オブジェクトと Engineer オブジェクトはどちらも Employee 型を使用して参照されますが、Java は実行時に実際のオブジェクトのオーバーライドされたメソッドを呼び出し、動的メソッド ディスパッチ (実行時ポリモーフィズム) を示します。
関連記事: メソッドのオーバーロードとメソッドのオーバーライド