【Java】レッスン5-8:インターフェースを理解しよう

ながみえ

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

今回は インターフェース について見ていきましょう。

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プログラミングの一歩を踏み出しましょう。

インターフェースの役割と特徴|抽象クラスとの違いを理解しよう

インターフェース はクラスが実装するための「契約」のようなものです。

インターフェースの中ではメソッドの宣言のみが行われ、具体的な処理は何も書きません。

これにより複数のクラスが共通の名前のメソッドを持つことができ、それぞれのクラスが独自にメソッドを実装することができます。

インターフェースの定義は interfaceキーワード を、実装は implementsキーワード を使って行います。

interface インターフェース名 {	// インターフェースの定義
    void メソッド名();		   // メソッドの名前のみ定義
}
class クラス名 implements インターフェース名 {	// インターフェースを実装したクラスの定義
    @Override					// Overrideアノテーション
    public void メソッド名() {	// メソッドをオーバーライドして具体的な実装
        // 処理内容
    }

インターフェース内のメソッドは前のレッスンで学習した抽象メソッドと同じものです。

ただし抽象クラス内で定義する場合と異なり、定義時にabstractキーワードは必要ありません。

インターフェースと抽象クラスの違いは以下の通りです。

比較項目インターフェース抽象クラス
目的実装すべきメソッドの契約(仕様)を定義共通の基本機能や状態を持たせ、拡張のための土台にする
多重継承可能(1つのクラスが複数のインターフェースを実装できる)不可(クラスは1つしか継承できない)
継承キーワードimplementsextends
フィールドpublic static final の定数のみインスタンス変数や定数を持てる
メソッド(Java 7以前)全て public abstract(実装なし)abstract メソッドと通常メソッドの両方を持てる
メソッド(Java 8以降)default メソッド(実装あり)や static メソッドも定義可通常メソッド・static メソッド・final メソッドも定義可
コンストラクタ定義できない定義できる(抽象クラス単体ではインスタンス化不可)
アクセス修飾子メソッドは常に publicフィールドやメソッドに自由なアクセス修飾子を付けられる
用途のイメージ「○○できる」という能力や役割の共有(例:Runnable「○○という種類」の共通部分をまとめる(例:Animal

インターフェースの実装例とコード解説

次のコード例は「Playable」というインターフェースを定義したものです。

ここではplaystopという2つのメソッドを定義していますが、実装内容は含まれていません。

このインターフェースを実装するクラスは、それぞれのメソッドを具体的に実装する必要があります。

interface Playable {	// Playableとう名前のインターフェースの定義
    void play();		// 抽象メソッドplayの定義
    void stop();		// 抽象メソッドstopの定義
}
class MusicPlayer implements Playable {	// インターフェースを実装したクラスの定義
    @Override
    public void play() {	// 抽象メソッドplayをオーバーライド
        System.out.println("音楽を再生します");
    }
    @Override
    public void stop() {	// 抽象メソッドstopをオーバーライド
        System.out.println("音楽を停止します");
    }
}

このようにMusicPlayerクラスはPlayableインターフェースを実装し、playstopメソッドに具体的な処理を記述しています。

まとめ|柔軟な設計を可能にするインターフェースの力

インターフェースはクラス間で共通の仕様を定め、複数のクラスで統一的な使い方を可能にする強力な仕組みです。

抽象クラスとの違いを理解することで、場面に応じた柔軟な設計ができるようになりました。

また、実際にインターフェースを定義し実装する手順を学んだことで、複数継承を活用した設計にも対応できる力がついています。

ここまでの知識は、より大規模で拡張性の高いプログラムを作るための大切な基盤です。

ぜひ、この経験を自分のコードに取り入れ、次のステップへと進んでいきましょう。

練習問題|図形ごとの面積計算でインターフェースを活用しよう

インターフェースを使って複数の図形の面積を計算するプログラムを作成しましょう。

この問題の要件

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

  1. Shapeというインターフェースを作成し、以下のメソッドを宣言すること:
    • calculateArea(): double – 図形の面積を計算する
  2. Shapeインターフェースを実装する以下のクラスを作成すること:
    • Rectangleクラス: 幅(width)と高さ(height)を持つ長方形。面積は幅×高さで計算する。
    • Circleクラス: 半径(radius)を持つ円。面積はπ×半径×半径で計算する。
  3. 各クラスのコンストラクタは必要な値を受け取り、対応するフィールドに設定すること。
  4. Mainクラスを作成し、ユーザーから図形の情報を入力して面積を計算・表示するプログラムを実装すること。

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

長方形の幅を入力してください: 5
長方形の高さを入力してください: 10
長方形の面積: 50.0
円の半径を入力してください: 3
円の面積: 28.274333882308138

この問題を解くヒント

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

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

正解のコードは上から順に以下のような構成となっています。

1:Scannerクラスをインポート
2:Shapeインターフェースの定義
  □ calculateAreaメソッドの定義
3:Rectangleクラスの定義とShapeインターフェースの実装
  □ widthフィールドをprivateで定義
  □ heightフィールドをprivateで定義
  □ Rectangleクラスのコンストラクタで幅と高さを受け取る
  □ calculateAreaメソッドのオーバーライド
    □ 幅と高さを掛けて面積を返す
4:Circleクラスの定義とShapeインターフェースの実装
  □ radiusフィールドをprivateで定義
  □ Circleクラスのコンストラクタで半径を受け取る
  □ calculateAreaメソッドのオーバーライド
    □ 円の面積を計算し返す
5:Mainクラスの定義
  □ mainメソッドの定義
  □ □ Scannerオブジェクトscannerの初期化
  □ □ 「長方形の幅を入力してください: 」と出力
  □ □ ユーザーから長方形の幅を入力し、widthに代入
  □ □ 「長方形の高さを入力してください: 」と出力
  □ □ ユーザーから長方形の高さを入力し、heightに代入
  □ □ Rectangleオブジェクトを作成し、長方形の面積を計算
  □ □ 「長方形の面積: 」と計算結果を出力
  □ □ 「円の半径を入力してください: 」と出力
  □ □ ユーザーから円の半径を入力し、radiusに代入
  □ □ Circleオブジェクトを作成し、円の面積を計算
  □ □ 「円の面積: 」と計算結果を出力

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

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

import java.util.Scanner;

// Shapeインターフェースの定義
/* 【穴埋め問題1】
ここにShapeインターフェースを定義し、calculateAreaメソッドを宣言してください。
*/

// Rectangleクラスの定義。Shapeインターフェースを実装する
class Rectangle /* 【穴埋め問題2】ここにShapeインターフェースを実装するコードを記述してください。 */ {
    private double width;
    private double height;

    // コンストラクタ。幅と高さを受け取る
    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }

    // インターフェースのcalculateAreaメソッドを実装
    /* 【穴埋め問題3】
    ここにインターフェースのcalculateAreaメソッドをオーバーライドして、長方形の面積を計算するコードを書いてください。
    */
}

// Circleクラスの定義。Shapeインターフェースを実装する
class Circle /* 【穴埋め問題4】ここにShapeインターフェースを実装するコードを記述してください。 */ {
    private double radius;

    // コンストラクタ。半径を受け取る
    public Circle(double radius) {
        this.radius = radius;
    }

    // インターフェースのcalculateAreaメソッドを実装
    /* 【穴埋め問題5】
    ここにインターフェースのcalculateAreaメソッドをオーバーライドして、円の面積を計算するコードを書いてください。
    */
}

// Mainクラスの定義。メインメソッドを含む
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        // ユーザーに長方形の幅と高さを入力させる
        System.out.print("長方形の幅を入力してください: ");
        double width = scanner.nextDouble();
        System.out.print("長方形の高さを入力してください: ");
        double height = scanner.nextDouble();

        // 長方形の面積を計算
        Shape rectangle = new Rectangle(width, height);
        System.out.println("長方形の面積: " + rectangle.calculateArea());

        // ユーザーに円の半径を入力させる
        System.out.print("円の半径を入力してください: ");
        double radius = scanner.nextDouble();

        // 円の面積を計算
        Shape circle = new Circle(radius);
        System.out.println("円の面積: " + circle.calculateArea());
    }
}

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

練習問題の解答と解説

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

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

Q
正解コード
import java.util.Scanner;

// Shapeインターフェースの定義
interface Shape {
    double calculateArea();
}

// Rectangleクラスの定義。Shapeインターフェースを実装する
class Rectangle implements Shape {
    private double width;
    private double height;

    // コンストラクタ。幅と高さを受け取る
    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }

    // インターフェースのcalculateAreaメソッドを実装
    @Override
    public double calculateArea() {
        return width * height;
    }
}

// Circleクラスの定義。Shapeインターフェースを実装する
class Circle implements Shape {
    private double radius;

    // コンストラクタ。半径を受け取る
    public Circle(double radius) {
        this.radius = radius;
    }

    // インターフェースのcalculateAreaメソッドを実装
    @Override
    public double calculateArea() {
        return Math.PI * radius * radius;
    }
}

// Mainクラスの定義。メインメソッドを含む
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        // ユーザーに長方形の幅と高さを入力させる
        System.out.print("長方形の幅を入力してください: ");
        double width = scanner.nextDouble();
        System.out.print("長方形の高さを入力してください: ");
        double height = scanner.nextDouble();

        // 長方形の面積を計算
        Shape rectangle = new Rectangle(width, height);
        System.out.println("長方形の面積: " + rectangle.calculateArea());

        // ユーザーに円の半径を入力させる
        System.out.print("円の半径を入力してください: ");
        double radius = scanner.nextDouble();

        // 円の面積を計算
        Shape circle = new Circle(radius);
        System.out.println("円の面積: " + circle.calculateArea());
    }
}
Q
正解コードの解説

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

インターフェースShapeの定義

interface Shape {
    double calculateArea();
}

まず、Shapeインターフェースが定義されています。

このインターフェースは、図形の面積を計算するためのcalculateArea()というメソッドの宣言を含んでいますが、具体的な実装は持っていません。

インターフェースは、クラスに対して「このメソッドを実装してください」と指示する役割を果たします。

Rectangleクラスの定義と実装

class Rectangle implements Shape {
    private double width;
    private double height;

    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }

    @Override
    public double calculateArea() {
        return width * height;
    }
}

RectangleクラスはShapeインターフェースを実装しています。

implementsキーワードを使うことで、Shapeインターフェースに定義されたメソッドcalculateArea()を具体的に実装しています。

長方形の面積は幅×高さで計算されます。

@Overrideアノテーションは、親のインターフェースからメソッドをオーバーライドしていることを明示しています。

Circleクラスの定義と実装

class Circle implements Shape {
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    @Override
    public double calculateArea() {
        return Math.PI * radius * radius;
    }
}

CircleクラスもShapeインターフェースを実装しており、こちらでは円の面積を計算するためのcalculateArea()メソッドが具体的に実装されています。

円の面積は公式に従い、Math.PI * radius * radiusで計算されます。

メインメソッドでの実行

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        // ユーザーに長方形の幅と高さを入力させる
        System.out.print("長方形の幅を入力してください: ");
        double width = scanner.nextDouble();
        System.out.print("長方形の高さを入力してください: ");
        double height = scanner.nextDouble();

        // 長方形の面積を計算
        Shape rectangle = new Rectangle(width, height);
        System.out.println("長方形の面積: " + rectangle.calculateArea());

        // ユーザーに円の半径を入力させる
        System.out.print("円の半径を入力してください: ");
        double radius = scanner.nextDouble();

        // 円の面積を計算
        Shape circle = new Circle(radius);
        System.out.println("円の面積: " + circle.calculateArea());

        scanner.close();
    }
}

メインメソッドでは、ユーザーから長方形の幅と高さ、そして円の半径を入力させ、それに基づいてRectangleCircleオブジェクトが作成されます。

各オブジェクトのcalculateArea()メソッドを呼び出して、図形の面積を計算して結果を表示します。

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

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

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

<<前のページ

学習記事一覧

次のページ>>

記事URLをコピーしました