MENU

【Java】レッスン5-06:メソッドのオーバーライドとは?仕組みと使い方を基礎から解説

tggaa478@yahoo.co.jp

一つ前のページではクラスの継承について学習しました。

今回は メソッドのオーバーライド について見ていきましょう。

Lesson1:基礎文法編
Lesson2:制御構造編
Lesson3:メソッド編
Lesson4:コレクション編
Lesson5:クラス

 ・Lesson5-1:クラスの基本を確認しよう
 ・Lesson5-2:コンストラクタを理解しよう
 ・Lesson5-3:カプセル化を理解しよう
 ・Lesson5-4:クラスメンバとインスタンスメンバを理解しよう
 ・Lesson5-5:クラスの継承を理解しよう
 ・Lesson5-6:メソッドのオーバーライドを理解しよう ◁今回はココ
 ・Lesson5-7:抽象クラスを理解しよう
 ・Lesson5-8:インターフェースを理解しよう
 ・確認問題5-☆1:モンスター捕獲ゲームを作ろう
 ・確認問題5-☆2:モンスターとのバトルゲームを作ろう
 ・確認問題5-☆3:マルバツゲーム(Tic-Tac-Toe)を作成しよう

<<前のページ

学習記事一覧

次のページ>>

Javaのメソッドオーバーライドとは?基本から丁寧に解説

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

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

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

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

あわせて読みたい
【Java】レッスン5-05:extendsで学ぶクラスの継承と使い方をマスターしよう
【Java】レッスン5-05:extendsで学ぶクラスの継承と使い方をマスターしよう

オーバーライドの定義と基本的な考え方

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

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

また親クラスのメソッドに@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で宣言されたメソッドはオーバーライドできないため注意が必要です。

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

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

オーバーライドの重要ポイントを総まとめ

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

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

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

練習問題|メソッドのオーバーライドで動物ごとの鳴き声を表示しよう

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

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

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

この問題の要件

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

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

ただし、以下のような実行結果となること。

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

この問題を解くヒント

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

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

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

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

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

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

Q
ヒント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メソッドを呼び出すコードを書いてください。
           出力は「犬は「ワンワン」と鳴きます」となります。
        */
    }
}

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

練習問題の解答と解説

この問題の正解コードとその解説は以下の通りです。

クリックして開いて確認してください。

Q
正解コード
// 親クラス:動物(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(); // 出力:犬は「ワンワン」と鳴きます
    }
}
Q
正解コードの解説

コードをブロックごとに分割して解説します。

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

もっと分かりやすい学習サイトにするために

この記事を読んで「ここが分かりにくかった」「ここが難しかった」等の意見を募集しています。

世界一わかりやすいJava学習サイトにするため、ぜひ 問い合わせフォーム からご意見下さい。

<<前のページ

学習記事一覧

次のページ>>

記事URLをコピーしました