【JAVA】レッスン5-06:メソッドのオーバーライドを理解しよう

記事内に商品プロモーションを含む場合があります

この記事で学べる知識:メソッドのオーバーライド

この記事の練習問題で使用する知識:
基礎構文、制御構造、メソッド、コレクション(レッスン1~4)クラスの定義と使用コンストラクタカプセル化クラスメンバとインスタンスメンバクラスの継承メソッドのオーバーライド抽象クラスインターフェース

<<前のページ テキストTop 次のページ>>

JAVAの「メソッドのオーバーライド」とは

この章ではJAVAにおける「メソッドのオーバーライド」の意味や使い方を学習します。必要ない方はここをクリックして練習問題へ飛びましょう。



メソッドのオーバーライドは、継承したクラスのメソッドを子クラスで再定義する技術です。

オーバーライドを使用することで、親クラスから継承されたメソッドを子クラスで新しい動作に変えることができます。

これによりプログラム全体の柔軟性と再利用性が高まります。

メソッドのオーバーライドを理解するためには「クラスの継承」の知識が必須となりますので、クラスの継承が分からいない人はまず↓↓の記事を確認しましょう。

【JAVA】レッスン5-05:クラスの継承を理解しよう【JAVA】クラスの継承に重点をおいた無料の解説と練習問題。クラスの継承の本質的な内容やコードの中での役割を、できる限り分かりやすく解説します。実践的な練習問題を通じてJAVAのスキルアップに繋がりますので、是非無料で挑戦してください。...
【初心者向け】Javaのオブジェクト指向の概念を表した図。特にクラスの継承、抽象クラス、インターフェース、オーバーライド、インスタンス生成を視覚的に分かりやすくまとめている。 本記事では「メソッドのオーバーライド」を中心に説明している。

メソッドのオーバーライドの基本概念

オーバーライドは親クラスに定義されたメソッドと同じ名前、引数、戻り値を持つメソッドを子クラスで再定義することを指します。

このときメソッドのシグネチャ(メソッド名、引数の数と型、戻り値の型)は親クラスのメソッドと一致している必要があります。

また親クラスのメソッドに@Overrideアノテーションを追加すると、オーバーライドであることが明示され、エラーが検出しやすくなります。

クラスの継承とオーバーライドの関係性

オーバーライドはクラスの継承を前提とした技術です。

親クラスのメソッドをそのまま利用するだけでなく、子クラス独自の動作を追加したい場合に役立ちます。

たとえば動物クラスに定義された「鳴く」メソッドを、犬や猫といった子クラスでオーバーライドすることで、それぞれの動物に応じた鳴き声を出すように変更することができます。

class Animal { //親クラス
    void makeSound() { //makeSoundメソッドの定義
        System.out.println("Some generic animal sound");
    }
}

class Dog extends Animal { //子クラス
    @Override //Overrideアノテーション
    void makeSound() { //親クラスと同じ名前のメソッド
        System.out.println("Woof");
    }
}

class Cat extends Animal { //子クラス
    @Override //Overrideアノテーション
    void makeSound() { //親クラスと同じ名前のメソッド
        System.out.println("Meow");
    }
}

この例ではAnimalクラスを継承したDogCatクラスが、それぞれの動物の鳴き声を出すようにmakeSoundメソッドをオーバーライドしています。

これによりDogオブジェクトのmakeSoundメソッドを呼び出すと「Woof」、CatオブジェクトのmakeSoundメソッドを呼び出すと「Meow」と表示されます。

オーバーライドの使用例と解説

オーバーライドは共通のメソッドを持つ複数の子クラスに対して異なる動作を実現する際に効果的です。

次のコード例では、動物園のシステムで各動物が異なる鳴き声を出すケースを示しています。

class Zoo {
    public static void main(String[] args) {
        Animal animal1 = new Dog();
        Animal animal2 = new Cat();

        animal1.makeSound();  // 出力: Woof
        animal2.makeSound();  // 出力: Meow
    }
}

この例ではZooクラスの中でDogCatクラスをAnimal型の変数に代入していますが、各オブジェクトのmakeSoundメソッドを呼び出すと、それぞれのクラスにオーバーライドされたメソッドが実行されます。

これにより動物ごとに異なる鳴き声を表現でき、オブジェクト指向の多態性(ポリモーフィズム)が実現されます。

注意点(アクセス修飾子のルールなど)

オーバーライドにはいくつかのルールがあります。

オーバーライドするメソッドは、親クラスのメソッドと同じかそれより広いアクセス修飾子である必要があります。

たとえば親クラスでprotectedと指定されている場合、オーバーライドする子クラスのメソッドはprotectedまたはpublicである必要があります。privatefinalで宣言されたメソッドはオーバーライドできないため注意が必要です。

また例外についてもルールがあります。

親クラスのメソッドが特定の例外をスローする場合、子クラスのオーバーライドメソッドは同じ例外か、それよりも狭い範囲の例外をスローする必要があります。

まとめ

メソッドのオーバーライドは、クラスの継承を活用してクラスごとの動作を実装する重要な技術です。

オーバーライドを使うことで、親クラスのメソッドを子クラスで独自に実装し、より柔軟で再利用性の高いコードを作成できます。

クラスの継承との関係やルールを正しく理解し、効果的に活用していきましょう。

練習問題5-6:動物の鳴き声を表示するプログラムを作ろう

動物の鳴き声を表示するプログラムを作成しましょう。

このプログラムでは動物の基本的な鳴き声を表示する「動物クラス」と、それを継承して「犬クラス」を作成します。

犬クラスではメソッドのオーバーライドを使って、犬が鳴くときの特有の鳴き声を表示します。

この問題の要件

以下の要件に従ってコードを完成させてください。

  1. Animalクラスを作成し、soundメソッドを定義すること。
    • soundメソッドは「動物は音を出します」と表示すること。
  2. Animalクラスを継承したDogクラスを作成し、soundメソッドをオーバーライドすること。
    • オーバーライドしたsoundメソッドでは「犬は「ワンワン」と鳴きます」と表示すること。
  3. Mainクラス内で以下の処理を行うこと。
    • Animalクラスのインスタンスを作成し、soundメソッドを呼び出すこと。
    • Dogクラスのインスタンスを作成し、soundメソッドを呼び出すこと。

ただし、以下のような実行結果となるコードを書くこと。

*****↓↓正解コードの実行結果の例↓↓*****

動物は音を出します
犬は「ワンワン」と鳴きます

この問題を解くヒント

1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。

ヒント1【コードの構成を見る】

正解のコードは上から順に以下のような構成となっています。
(※下記の□はコード内のインデントを表しています)

1:Animalクラスの定義
  □ soundメソッドの定義
  □ □ 「動物は音を出します」と出力する

2:Dogクラスの定義(Animalクラスを継承)
  □ soundメソッドのオーバーライド
  □ □ 「犬は「ワンワン」と鳴きます」と出力する

3:Mainクラスの定義
  □ mainメソッドの定義
  □ □ AnimalクラスのインスタンスgenericAnimalを作成
  □ □ genericAnimalのsoundメソッドを呼び出す
  □ □ DogクラスのインスタンスmyDogを作成
  □ □ myDogのsoundメソッドを呼び出す

ヒント2【穴埋め問題にする】

以下のコードをコピーし、コメントに従ってコードを完成させて下さい。

// 親クラス:動物(Animal)
class Animal {
    // 動物の鳴き声を表示するメソッド
    public void sound() {
        System.out.println("動物は音を出します");
    }
}

// 子クラス:犬(Dog) - Animalクラスを継承
class Dog extends Animal {
    /* 【穴埋め問題1】
       ここにsoundメソッドをオーバーライドし、「犬は「ワンワン」と鳴きます」と表示するコードを書いてください。
    */
}

// メインクラス
public class Main {
    public static void main(String[] args) {
        /* 【穴埋め問題2】
           ここにAnimalクラスのインスタンスgenericAnimalを作成し、soundメソッドを呼び出すコードを書いてください。
           出力は「動物は音を出します」となります。
        */
        
        /* 【穴埋め問題3】
           ここにDogクラスのインスタンスmyDogを作成し、soundメソッドを呼び出すコードを書いてください。
           出力は「犬は「ワンワン」と鳴きます」となります。
        */
    }
}

以上がこの問題の穴埋めコードです。

このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。



解答例と解説

この問題の一つの正解例とそのコードの解説を以下に示します。

正解コードの例

例えば以下のようなプログラムが考えられます。

// 親クラス:動物(Animal)
class Animal {
    // 動物の鳴き声を表示するメソッド
    public void sound() {
        System.out.println("動物は音を出します");
    }
}

// 子クラス:犬(Dog) - Animalクラスを継承
class Dog extends Animal {
    // soundメソッドをオーバーライドして、犬特有の鳴き声を表示する
    @Override
    public void sound() {
        System.out.println("犬は「ワンワン」と鳴きます");
    }
}

// メインクラス
public class Main {
    public static void main(String[] args) {
        // Animalクラスのインスタンスを作成してsoundメソッドを呼び出す
        Animal genericAnimal = new Animal();
        genericAnimal.sound(); // 出力:動物は音を出します
        
        // Dogクラスのインスタンスを作成してsoundメソッドを呼び出す
        Dog myDog = new Dog();
        myDog.sound(); // 出力:犬は「ワンワン」と鳴きます
    }
}

正解コードの解説

正解コードの解説を以下に示します。

この解説を通して、Javaの継承やメソッドのオーバーライドの基礎を学びましょう。

親クラス:Animal

class Animal {
    // 動物の鳴き声を表示するメソッド
    public void sound() {
        System.out.println("動物は音を出します");
    }
}

Animal クラスは基本的な動物の機能を持つ親クラスです。

sound メソッドには「動物は音を出します」と表示するコードが含まれており、動物全般の鳴き声を表現しています。

子クラス:Dog

class Dog extends Animal {
    @Override
    public void sound() {
        System.out.println("犬は「ワンワン」と鳴きます");
    }
}

Dog クラスは Animal クラスを継承しており、動物の一種である「犬」を表しています。

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

@Override は、Animal クラスの sound メソッドを Dog クラス独自の実装に書き換えていることを示しています。

オーバーライド(上書き)によって、Dog クラスの sound メソッドを呼び出すと「犬は「ワンワン」と鳴きます」と表示され、犬特有の鳴き声が表現されるようになります。

オーバーライドすることで、親クラスから継承したメソッドを子クラスの要件に合わせてカスタマイズすることができます。

メインクラス:Main

public class Main {
    public static void main(String[] args) {
        Animal genericAnimal = new Animal();
        genericAnimal.sound(); // 出力:動物は音を出します

        Dog myDog = new Dog();
        myDog.sound(); // 出力:犬は「ワンワン」と鳴きます
    }
}

Main クラスには main メソッドがあり、プログラムの実行がここから始まります。

このメソッドの役割はAnimal クラスと Dog クラスのインスタンスを作成し、それぞれの sound メソッドを呼び出すことです。

インスタンスの生成とメソッドの呼び出し
  • genericAnimalAnimal クラスのインスタンスで、sound メソッドを呼び出すと「動物は音を出します」が表示されます。
  • myDogDog クラスのインスタンスで、sound メソッドを呼び出すと「犬は「ワンワン」と鳴きます」が表示され、Dog クラスでオーバーライドされたメソッドが適用されます。

まとめ

このコードではJavaの基本的なオブジェクト指向の概念である「継承」と「メソッドのオーバーライド」について学びました。

親クラスと子クラスの関係を通じて、通の動作を持たせながらも、それぞれのクラスの特性に応じた動作を実現できることがわかります。

Javaのオブジェクト指向を使って柔軟なプログラムを作成するための第一歩として、このコードを理解し、実際に変更を加えてみましょう。

<<前のページ テキストTop 次のページ>>

この記事への質問・コメント

この記事を作成するにあたりAIを活用しています。

問題ないことは確認していますが、もし間違いや表現の違和感などありましたら、ご指摘頂けると大変助かります。






    JAVAテキスト&問題集へ戻る
    トップページへ戻る