Javaでマスターする!オーバーライドのたった7つのステップ

Javaプログラミング初心者が学ぶオーバーライドの基本と応用方法 Java
この記事は約26分で読めます。

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればサンプルコードを活用して機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

プログラムの世界は広大で、初心者が入門するにはとても親しみやすいガイダンスが必要です。

この記事では、Java言語の特性やオブジェクト指向プログラムの基本を徹底的に説明し、豊富なサンプルコードを用いてオーバーライドの使い方を解説します。

プログラム作成やコーディング技法に不慣れな方でも、ステップバイステップで学んでいけるような構成となっています。

それでは、Javaの世界へ一緒に踏み出しましょう!

●Javaとは?

Javaは、広く使われているプログラム言語の一つで、その特徴はプラットフォーム独立性、オブジェクト指向性、安全性などが挙げられます。

特に、オブジェクト指向プログラムの理念を採用していることが、Javaの大きな特徴と言えます。

ここで、Java言語の主な特性について少し詳しく見ていきましょう。

○プログラム言語としての特性

□プラットフォーム独立性

Javaは「一度書けばどこでも動く」という理念の下、異なるハードウェアやオペレーティングシステム上で同一のJavaプログラムが動作することを目指しています。

この特性はJava Virtual Machine(JVM)という仮想マシン上でプログラムが実行されることにより実現しています。

□オブジェクト指向性

Javaはオブジェクト指向プログラミング(OOP)の原則を採用しており、これによってプログラムの再利用性や拡張性が高まります。

OOPの原則には、カプセル化、継承、多様性などがあります。

□安全性

Javaはメモリ管理や例外処理を行う構造になっており、これによってプログラムの安全性が向上します。

特に、メモリリークやポインタの誤操作から来るバグを防ぐ仕組みが強化されています。

□豊富なAPIとライブラリ

Javaは基本的なプログラム言語機能に加え、多くのAPI(アプリケーションプログラムインターフェイス)やライブラリが提供されています。

これにより、プログラム開発者は効率的かつ迅速にアプリケーションの開発が行えます。

○オブジェクト指向プログラムの基本

オブジェクト指向プログラムは、プログラムを「オブジェクト」という単位で管理し、それらが相互にコミュニケーションを取りながら動作するという思想に基づいています。

ここでは、その基本概念としてクラスとオブジェクト、そしてオーバーライドに焦点を当てて解説します。

□クラスとオブジェクト

■クラス(Class)

オブジェクトの設計図のようなもので、オブジェクトの属性(変数)と振る舞い(メソッド)を定義します。

■オブジェクト(Object)

クラスから生成される実体で、クラスで定義された属性と振る舞いを持ちます。

□オーバーライド

オーバーライドは、継承関係にあるクラス間で同名のメソッドを再定義する機能です。

これにより、子クラスは親クラスのメソッドをそのまま利用するのではなく、新たな振る舞いを実装することが可能になります。

●オーバーライドとは?

オーバーライドは、Javaのオブジェクト指向プログラミングの基本中の基本であり、サブクラスでスーパークラスのメソッドを新しく定義し直すことを言います。

具体的な利点や用途、そしてこれからご紹介するサンプルコードを通して、初心者でも簡単に理解できるよう説明します。

オーバーライドの具体的な過程は、スーパークラスで定義されたメソッドをサブクラスで再定義することになります。

この時、メソッドのシグネチャ(メソッド名、引数の型と数)は同じである必要がありますが、メソッドの内部の処理内容を変更することが可能です。

これにより、異なるクラスで異なる動作をさせることができます。

○基本的な概念の解説

オーバーライドは、Javaの強力な機能の一つです。

先程説明した通り、オーバーライドを利用することで、サブクラスでスーパークラスのメソッドを再定義することができます。

これにより、一貫したインターフェイスを保ちながら、異なるクラスに異なる動作を実装することができます。

さらに深堀りすると、オーバーライドはポリモーフィズム(多様性)の一形態であり、これにより異なるクラスのオブジェクトを同一のインターフェイスで操作できるようになります。

また、オーバーライドを行う際には、アノテーション@Overrideを使用することが推奨されます。

このアノテーションを使用することで、コンパイラがメソッドが正しくオーバーライドされているかをチェックしてくれます。

○オーバーライドの重要性

オーバーライドの重要性は、コードの再利用性と可読性の向上にあります。

オーバーライドを行うことで、既存のクラスを拡張し、新しい機能を追加することが可能です。

このことが、コードの再利用性を高め、開発効率を向上させます。

また、オーバーライドを利用すると、異なるクラスで共通のインターフェイスを持つメソッドを定義できるため、プログラムの可読性も向上します。

この特性により、プログラムの保守や拡張が容易になります。

さらに、オーバーライドはオブジェクト指向プログラミングのポリモーフィズムを実現する重要な要素となります。

これにより、プログラムの設計がより柔軟かつ効率的に行えるようになります。

○オーバーライドの利点と注意点

オーバーライドの主な利点は、クラスの階層構造を作成し、コードの再利用性を高めることができる点です。

また、オーバーライドを利用すると、サブクラスでスーパークラスのメソッドの動作を変更したり、拡張することが可能となります。

ただし、オーバーライドを行う際には注意が必要です。

特に、オーバーライドされたメソッドが意図しない動作をしないよう、メソッドのシグネチャ(メソッド名と引数の型と数)を正しく維持することが重要です。

また、オーバーライドするメソッドのアクセス修飾子は、スーパークラスのそれよりも狭い範囲には設定できません。

●オーバーライドの基本的な使い方

オーバーライドは、Javaの重要な特性であり、オブジェクト指向プログラミングの基本的な技法の一つです。

オーバーライドを行う際には、親クラスに存在するメソッドを子クラスで再定義するというプロセスを経ます。

ここでは、オーバーライドの基本的な使い方を理解し、簡単なサンプルコードを通じて、オーバーライドの仕組みを解説します。

まずは、オーバーライドの基本的なコンセプトを把握するところから始めましょう。

オーバーライドは、親クラスに定義されたメソッドを子クラスで新しく定義し直すことで行われます。

子クラスにおける新しいメソッド定義は、親クラスのメソッドの振る舞いを変更や拡張することが可能です。

こうした操作が行えるのは、Javaがオブジェクト指向プログラム言語であるためです。

○サンプルコード1:簡単なオーバーライドの方法

まずは、基本的なオーバーライドの方法を説明します。

下記のサンプルコードは、親クラス「Animal」に「greet」メソッドを定義し、子クラス「Dog」でこのメソッドをオーバーライドしています。

// 親クラス Animalを定義
public class Animal {
    public void greet() {
        System.out.println("こんにちは、私は動物です。");
    }
}

// 子クラス Dogを定義し、Animalクラスを継承
public class Dog extends Animal {
    // Animalクラスのgreetメソッドをオーバーライド
    public void greet() {
        System.out.println("こんにちは、私は犬です。");
    }
}

// メインクラス
public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.greet();
    }
}

このコードでは、Animalクラスを継承したDogクラスにおいて、greetメソッドをオーバーライドしています。

オーバーライドされたメソッドは、新しいメッセージをコンソールに出力します。

このコードを実行すると、コンソールには「こんにちは、私は犬です。」と表示されます。

この結果は、Dogクラスにおいてgreetメソッドがオーバーライドされ、新しいメソッド定義が用いられるためです。

○サンプルコード2:親クラスのメソッドを利用する方法

Java言語におけるオーバーライド技法は非常に有用で、特に親クラスのメソッドを活用する場面ではその利便性が顕著に現れます。

ここでは、Javaプログラムにおいて親クラスのメソッドを利用しながら、子クラスで独自の機能を追加する一例として、親クラスのメソッドを活用する方法をサンプルコードとともに紹介します。

まずは基本となる親クラスを定義します。

ここでは「Vehicle」という名のクラスを作成し、その中に「speedUp」というメソッドを実装します。

このメソッドは、車両の速度を上げるというシンプルな機能を持ちます。

public class Vehicle {
    public void speedUp() {
        System.out.println("車両の速度を上げます");
    }
}

このコードを実行すると、「車両の速度を上げます」というメッセージが表示される結果となります。

次に、この親クラスを継承した子クラス「Car」を作成します。

この子クラスでは、親クラスの「speedUp」メソッドをオーバーライドし、更に新たな機能として「playMusic」メソッドを追加します。

public class Car extends Vehicle {
    @Override
    public void speedUp() {
        super.speedUp();
        System.out.println("カー専用の加速機能を追加します");
    }

    public void playMusic() {
        System.out.println("音楽を再生します");
    }
}

このコードでは、親クラスであるVehicleクラスのspeedUpメソッドをオーバーライドしています。

super.speedUp()という記述により、親クラスの同名のメソッドを呼び出しており、「カー専用の加速機能を追加します」という新しい機能が追加される形となります。

また、新しいメソッドとしてplayMusicメソッドも追加されており、これにより「音楽を再生します」という機能も利用可能となります。

さて、これでコードの解説は終わりです。

続いて、このコードを実行した場合の動作を確認しましょう。

具体的な実行コードは次のようになります。

public class Main {
    public static void main(String[] args) {
        Car myCar = new Car();
        myCar.speedUp();
        myCar.playMusic();
    }
}

このコードを実行すると、まず「車両の速度を上げます」と表示された後に、「カー専用の加速機能を追加します」というメッセージが表示されます。

これは、CarクラスのspeedUpメソッド内で親クラスのspeedUpメソッドが呼び出されることによるものです。

その後、「音楽を再生します」というメッセージが表示されることで、playMusicメソッドが正しく動作していることが確認できます。

●オーバーライドの応用例

Javaプログラミング学習を深める上で欠かせないのが、オーバーライドの技法です。

オーバーライドは、サブクラスでスーパークラスのメソッドを新しい機能で再定義するテクニックです。

ここでは、多様性を活用したオーバーライドの応用例と、それに付随するサンプルコード3を解説します。

細かく分析しながら進めていきましょう。

○サンプルコード3:多様性を活用したオーバーライド

まず、このサンプルコードでは多様性を活用したオーバーライド方法を解説します。

オーバーライドを応用した場合、プログラムの拡張性と柔軟性が増し、さまざまな機能を効率的に実装できるようになります。

下記のコードは、動物クラス(Animal)とそのサブクラスである犬クラス(Dog)と猫クラス(Cat)を作成し、それぞれのクラスで「voice」メソッドをオーバーライドしています。

このコードを実行すると、オブジェクトの型に応じて異なる「voice」メソッドが呼び出され、それぞれの動物の声が出力される結果になります。

// 動物クラスの作成
class Animal {
    void voice() {
        System.out.println("動物の声");
    }
}

// 犬クラス(動物クラスを継承)の作成
class Dog extends Animal {
    // voiceメソッドをオーバーライド
    @Override
    void voice() {
        System.out.println("ワンワン");
    }
}

// 猫クラス(動物クラスを継承)の作成
class Cat extends Animal {
    // voiceメソッドをオーバーライド
    @Override
    void voice() {
        System.out.println("ニャーン");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal myAnimal = new Animal();
        Animal myDog = new Dog();
        Animal myCat = new Cat();

        myAnimal.voice();
        myDog.voice();
        myCat.voice();
    }
}

このコードでは、Animalクラスを基にDogクラスとCatクラスを作成しています。

そして、DogクラスとCatクラスではvoiceメソッドをオーバーライドしており、それぞれの動物特有の声を出力します。

@Overrideアノテーションは、メソッドが正確にオーバーライドされているかコンパイラにチェックさせる役割を持ちます。

このコードを実行すると、次のような結果が得られます。

まず、Animal型のmyAnimalオブジェクトから呼び出されるvoiceメソッドは、基底クラスであるAnimalクラスのvoiceメソッドが実行され、”動物の声”と出力されます。

次に、myDogオブジェクトとmyCatオブジェクトから呼び出されるvoiceメソッドは、それぞれのオーバーライドされたメソッドが実行されるため、”ワンワン”と”ニャーン”が出力されます。

○サンプルコード4:抽象クラスを使ったオーバーライド

Javaプログラミングの学習を進めていく上で、抽象クラスを使ったオーバーライドは避けて通れないトピックとなります。

ここでは、Java言語での抽象クラスの利用とそれを活用したオーバーライドの技法に関して、細かい部分まで詳しく解説します。

まず初めに、抽象クラスとは何かを理解することが重要です。

抽象クラスは、いくつかの共通の特性を持つクラス群に共通の基盤を提供する役割を果たします。

これは、具体的な実装を持たない一つ以上のメソッド(抽象メソッド)を含むクラスのことです。

では、具体的なサンプルコードを見ながら、その詳細について説明しましょう。

abstract class Animal {
    // 抽象メソッドの宣言
    abstract void sound();
}

class Dog extends Animal {
    // 抽象メソッドのオーバーライド
    void sound() {
        System.out.println("ワンワン");
    }
}

class Cat extends Animal {
    // 抽象メソッドのオーバーライド
    void sound() {
        System.out.println("ニャー");
    }
}

public class Main {
    public static void main(String[] args) {
        // インスタンス生成
        Animal myDog = new Dog();
        Animal myCat = new Cat();

        // メソッドの呼び出し
        myDog.sound();
        myCat.sound();
    }
}

このコードでは抽象クラスAnimalを使っています。

この抽象クラスには、soundという抽象メソッドが定義されており、DogクラスとCatクラスではこの抽象メソッドをオーバーライドして具体的な実装を提供しています。

このコードを実行すると、それぞれのクラスのsoundメソッドが呼び出され、”ワンワン”と”ニャー”という文字列がコンソールに表示されます。

さらにこのサンプルコードは、オブジェクト指向プログラミングのポリモーフィズムの一例でもあります。

Animalクラスの変数でDogクラスやCatクラスのオブジェクトを参照できるのは、Javaが型の多様性をサポートしているためです。

このような実装は特に、大規模なプログラムや複数のプログラマーが共同で作業するプロジェクトにおいて非常に有用です。

クラス間の関係を明確にし、コードの整理と管理を容易にする効果があります。

それでは、このコードの実行結果について見てみましょう。

Mainクラスのmainメソッド内でDogクラスとCatクラスのインスタンスを作成し、それぞれのsoundメソッドを呼び出しています。

結果として、コンソールには次のような出力が表示されます。

ワンワン
ニャー

この出力から、DogクラスとCatクラスがそれぞれAnimalクラスのsoundメソッドを適切にオーバーライドし、期待した動作をしていることが確認できます。

●オーバーライドの注意点と対処法

Java言語を利用したプログラミングでは、オーバーライドは非常に重要な概念として位置づけられます。

オーバーライドは親クラスから継承したメソッドを子クラスで変更することができる技術です。

ただし、この技術を利用する際にはいくつかの注意点があります。

ここでは、それらの注意点とそれに対応する方法を詳細に解説します。

○ポイント1:アノテーションの利用

Javaにおけるオーバーライドの際、@Overrideアノテーションを使用することは良い習慣です。

このアノテーションをメソッドの前に付けることで、コンパイラーにそのメソッドが親クラスのメソッドをオーバーライドしていることを明示します。

このコードではアノテーションを使用してオーバーライドを示しています。

class 親クラス {
    void メソッド() {
        // 何らかの処理
    }
}

class 子クラス extends 親クラス {
    @Override
    void メソッド() {
        // 何らかの処理
    }
}

このコードを実行すると、子クラスが親クラスの「メソッド」をオーバーライドして新しい処理を行う結果が得られます。

もしメソッドのオーバーライドが正しく行われていない場合、@Overrideアノテーションの存在によってコンパイルエラーが発生します、これにより、プログラマは早期にエラーをキャッチできます。

○ポイント2:適切なアクセス修飾子の選定

オーバーライドする際には、アクセス修飾子の選定も非常に重要です。

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

public class 親クラス {
    protected void メソッド() {
        // 何らかの処理
    }
}

class 子クラス extends 親クラス {
    @Override
    public void メソッド() {
        // 何らかの処理
    }
}

このコードでは、親クラスの「メソッド」はprotectedアクセス修飾子を持っているため、子クラスのオーバーライドされたメソッドはpublicまたはprotectedである必要があります。

privateであると、オーバーライドとは認識されません。

○ポイント3:superキーワードの活用方法

オーバーライド時には、superキーワードを用いて親クラスのメソッドを呼び出すことも可能です。

これにより、新しい機能を追加しつつ、親クラスのメソッドの機能も保持することができます。

class 親クラス {
    void メソッド() {
        System.out.println("親クラスのメソッド");
    }
}

class 子クラス extends 親クラス {
    @Override
    void メソッド() {
        super.メソッド();
        System.out.println("子クラスのメソッド");
    }
}

public class メインクラス {
    public static void main(String[] args) {
        子クラス インスタンス = new 子クラス();
        インスタンス.メソッド(); // 親クラスのメソッド → 子クラスのメソッド と出力されます
    }
}

このコードを実行すると、「親クラスのメソッド」の後に「子クラスのメソッド」と表示されます。

これにより、オーバーライドされたメソッド内で親クラスのメソッドを利用することができます。

このような技法は、コードの再利用性を高めることができます。

●オーバーライドのカスタマイズ方法

オーバーライドはJavaの重要な機能の一つであり、クラス間でメソッドの挙動をカスタマイズする際に非常に効果的です。

ここでは、オーバーライドを活用したカスタムメソッドの作成に焦点を当てて解説します。

○サンプルコード5:オーバーライドを活用したカスタムメソッドの作成

まずはオーバーライドを活用したカスタムメソッドの作成方法を解説します。

具体的なコード例と共に、その背後にある理論も詳細に説明します。

// 親クラス Animal を作成します。このクラスには、sound メソッドを持たせます。
public class Animal {
    public void sound() {
        System.out.println("動物の声");
    }
}

// 子クラス Dog を作成します。このクラスは Animal クラスを継承し、sound メソッドをオーバーライドします。
public class Dog extends Animal {
    @Override
    public void sound() {
        System.out.println("ワンワン");
    }
}

// メインクラスで動作を確認します。
public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.sound();
    }
}

このコードを実行すると、「ワンワン」と表示されます。

このコードでは、Animal クラスという親クラスを作成し、その中にsoundメソッドを定義しています。

その後、Dogクラスという子クラスを作成し、soundメソッドをオーバーライドして独自の実装を加えます。

これにより、Dogクラスのインスタンスがsoundメソッドを呼び出すと、オーバーライドしたメソッドが実行されることが確認できます。

さて、次にこのコードのポイントを細かく説明します。

まず、@Overrideアノテーションを使用している点です。

このアノテーションは、メソッドが親クラスのメソッドをオーバーライドしていることを示すマークとして使います。

これにより、意図しないメソッドのオーバーライドを避けることができ、コードの保守性が向上します。

また、メソッドのオーバーライドは、子クラスが親クラスのメソッドを継承しつつ、その挙動を変更するための方法として利用されます。

この特性を活かして、異なるクラス間で共通のインターフェイスを持たせつつ、それぞれのクラスで異なる挙動を実装することが可能となります。

さらに詳しく言うと、このコード例ではAnimalクラスのsoundメソッドが「動物の声」と表示するシンプルな挙動を持つメソッドとして定義されています。

そして、Dogクラスではこのメソッドをオーバーライドして、「ワンワン」と表示する挙動を持たせています。

このコードを実行すると、「ワンワン」という文字列がコンソールに表示されます。

この結果から、Dogクラスのインスタンスがsoundメソッドを呼び出した際に、オーバーライドしたDogクラスのsoundメソッドが呼び出されることが確認できます。

これにより、異なる動物クラスを作成し、それぞれに独自のsoundメソッドを実装することで、多様性を持たせたプログラムを作成できます。

○サンプルコード6:動的メソッドディスパッチの利用

動的メソッドディスパッチは、オーバーライドされたメソッドが実行時にどのメソッドを呼び出すかを決定する技術です。

これはJavaの重要な特性であり、多様性とオブジェクト指向プログラミングを理解するうえで非常に役立つ概念です。

動的メソッドディスパッチは、オーバーライドされたメソッドが呼び出される際に、オブジェクトの型ではなく、オブジェクトのインスタンスに基づいてどのメソッドを呼び出すかを決定します。

つまり、コンパイル時ではなく実行時にどのメソッドが呼び出されるかが決まるのです。

では、サンプルコードを見ながら、動的メソッドディスパッチの利用方法を説明していきます。

class Vehicle {
    void run() {
        System.out.println("車両が走行しています");
    }
}

class Car extends Vehicle {
    void run() {
        System.out.println("車が走行しています");
    }
}

class Bike extends Vehicle {
    void run() {
        System.out.println("バイクが走行しています");
    }
}

public class Main {
    public static void main(String[] args) {
        Vehicle myVehicle = new Vehicle();
        Vehicle myCar = new Car();
        Vehicle myBike = new Bike();

        myVehicle.run();
        myCar.run();
        myBike.run();
    }
}

このコードでは、Vehicleクラスを定義し、そのクラスを継承するCarクラスとBikeクラスを作成しています。

各クラスには、runメソッドがあり、それぞれ異なるメッセージを出力します。

次に、Mainクラスのmainメソッド内で、Vehicleクラスのオブジェクトと、その子クラスであるCarクラスとBikeクラスのオブジェクトをVehicle型の変数に格納します。

そして、それぞれのrunメソッドを呼び出しています。

このコードを実行すると、それぞれのrunメソッドが出力するメッセージがコンソールに表示されます。

それでは、実行結果を見てみましょう。

実行した際に表示される結果は次の通りです。

車両が走行しています
車が走行しています
バイクが走行しています

これにより、動的メソッドディスパッチがJavaでどのように動作するかを表しています。

具体的には、runメソッドがオーバーライドされ、それぞれのクラスで異なる実装が提供されているため、オブジェクトの実際の型に基づいて適切なメソッドが呼び出されることがわかります。

○サンプルコード7:オーバーライドを利用したデザインパターン

Javaのプログラム作成過程において、オーバーライドはコーディング技法の1つとして不可欠な存在となっています。

ここでは、オーバーライドを利用したデザインパターンに関するサンプルコードをご紹介し、その応用法と注意点を詳細に解説します。

まず、このコードではTemplate Methodパターンを使って具体的な実装を行います。

このデザインパターンは、スーパークラスで流れを定義し、サブクラスでその流れの中の一部のみをオーバーライドすることで異なる振る舞いを実現するパターンです。

ここでは、簡単なプログラム作成のサンプルとして、Beverageクラスをスーパークラスとし、TeaとCoffeeという2つのサブクラスを作成します。

まずはスーパークラスBeverageを作成します。

public abstract class Beverage {

    // テンプレートメソッド
    public final void prepareRecipe() {
        boilWater();
        brew();
        pourInCup();
        addCondiments();
    }

    public void boilWater() {
        System.out.println("お湯を沸かします");
    }

    public abstract void brew(); // 抽象メソッド

    public void pourInCup() {
        System.out.println("カップに注ぎます");
    }

    public abstract void addCondiments(); // 抽象メソッド
}

このコードでは、Beverageクラスという抽象クラスを定義しています。

そして、prepareRecipeというテンプレートメソッドを利用して、作成する飲み物の調理手順を規定しています。

さらに、brewaddCondimentsという2つの抽象メソッドを宣言し、これらのメソッドがサブクラスでオーバーライドされることを期待しています。

次に、この抽象クラスを継承したTeaとCoffeeクラスを作成します。

public class Tea extends Beverage {

    public void brew() {
        System.out.println("ティーバッグを浸します");
    }

    public void addCondiments() {
        System.out.println("レモンを追加します");
    }
}

public class Coffee extends Beverage {

    public void brew() {
        System.out.println("コーヒーを淹れます");
    }

    public void addCondiments() {
        System.out.println("砂糖とミルクを追加します");
    }
}

TeaクラスとCoffeeクラスでは、brewaddCondimentsメソッドをオーバーライドし、それぞれの飲み物に適した調理方法を定義しています。

次に、このコードを実行すると、次のような結果が得られます。

public class Main {
    public static void main(String[] args) {
        Beverage tea = new Tea();
        tea.prepareRecipe();

        System.out.println();

        Beverage coffee = new Coffee();
        coffee.prepareRecipe();
    }
}

このコードを実行すると、ティーとコーヒーそれぞれの調理手順がコンソールに表示されます。

具体的には、ティーの場合は「お湯を沸かします」、「ティーバッグを浸します」、「カップに注ぎます」、「レモンを追加します」という手順が、コーヒーの場合は「お湯を沸かします」、「コーヒーを淹れます」、「カップに注ぎます」、「砂糖とミルクを追加します」という手順が表示されるのです。

この実行結果からわかるように、Template Methodパターンを利用することで、特定の手順に変更を加えつつ、他の手順は変更せずに再利用することが可能となります。

このような特性は、オーバーライドを利用したデザインパターンの力強い利点となります。

まとめ

オーバーライドはJavaプログラミングにおいて中心的な役割を果たしています。

この記事を通して、オーバーライドの基本から応用、さらには注意点やカスタマイズ方法までを解説しました。

初心者の方でも、次のポイントをしっかり理解することで、オーバーライドを効果的に使用することができるでしょう。

Javaのオーバーライドに関する知識を身につけることで、プログラミングの幅と深さを一段と広げることができます。

この記事を参考に、自身のコーディング技法をさらに磨き上げて、Javaプログラミングの世界を存分に楽しんでください。