JAVA練習問題4-5:インターフェースを理解しよう

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

JAVAの初心者向け問題4-5:インターフェースを理解しよう

この問題を解くために必要な知識:
【レベル1~3の知識】
コメントの書き方、変数と定数、基本データ型とプリミティブ型、四則演算と論理演算、入力と出力(Scannerクラス)、配列、分岐処理(if、if~else、switch)、繰り返し処理(for、while、do~while)、メソッドの定義と呼び出し、メソッドの戻り値、メソッドのオーバーロード、例外処理(try-catch文、throws、throw)、クラスの定義と使用、インスタンス、コンストラクタ、コレクションの基礎、コレクション(List, ArrayList)、コレクション(HashSet, TreeSet)、コレクション(HashMap, TreeMap)、

【レベル4の知識】
ゲッターとセッター、カプセル化、クラスメンバ、インスタンスメソッド、クラスの継承抽象クラス、インターフェース

<<前の問題 問題集Top 次の問題>>

JAVAの文法「インターフェース」とは

ここではインターフェースの意味や使い方を復習します。必要ない方はここをクリックして練習問題へ飛びましょう。



Javaの「インターフェース」は、クラスが実装すべきメソッドの契約を定義する仕組みです。

インターフェースは、メソッドの宣言のみを含み、その具体的な実装はサブクラスが行います。

これにより、異なるクラス間で共通の機能を持たせつつ、各クラスで異なる実装を提供することが可能です。

インターフェースの定義

インターフェースはinterfaceキーワードを使って定義します。

たとえば、次のようにAnimalインターフェースを定義できます。

interface Animal {
    void makeSound(); // メソッドの宣言
}

ここでは、makeSound()というメソッドの宣言だけが記述されています。

具体的な内容は記載されておらず、このインターフェースを実装するクラスがメソッドの詳細を提供します。

インターフェースを実装するクラス

インターフェースを実装するクラスはimplementsキーワードを使います。

次に、DogCatクラスがAnimalインターフェースを実装する例を示します。

class Dog implements Animal {
    @Override
    public void makeSound() {
        System.out.println("ワンワン");
    }
}

class Cat implements Animal {
    @Override
    public void makeSound() {
        System.out.println("ニャーニャー");
    }
}

DogCatは、Animalインターフェースを実装しており、それぞれmakeSound()メソッドに独自の実装を提供しています。

インターフェースの利点

インターフェースは、多重継承の代替手段として使われ、Javaではクラスは1つの親クラスしか継承できませんが、複数のインターフェースを実装することが可能です。

これにより、クラスに柔軟な設計をもたらします。

例えば、次のようにRunnableインターフェースとAnimalインターフェースの両方を実装することができます。

class RobotDog implements Animal, Runnable {
    @Override
    public void makeSound() {
        System.out.println("電子音");
    }

    @Override
    public void run() {
        System.out.println("走る");
    }
}

このように、RobotDogAnimalインターフェースのmakeSound()と、Runnableインターフェースのrun()を実装しています。

インターフェースのデフォルトメソッド

Java 8以降、インターフェースにデフォルトメソッドを追加できるようになりました。

デフォルトメソッドは、インターフェース内で実装を持つメソッドです。

interface Animal {
    void makeSound();
    
    default void sleep() {
        System.out.println("眠る");
    }
}

これにより、すべてのAnimalを実装するクラスは、sleep()メソッドを自動的に持ちますが、必要に応じてこのメソッドをオーバーライドすることも可能です。

まとめ

Javaのインターフェースは、クラスに特定の動作を強制しつつ、各クラスごとに異なる実装を提供する仕組みです。

また、複数のインターフェースを実装できる点が、Javaの設計を柔軟にします。

インターフェースを使いこなすことで、コードの拡張性や再利用性が向上します。




JAVA練習問題4-5_インターフェースを使った図形の面積計算プログラム

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

この問題の要件

以下の要件に従って作成して下さい。

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

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

----- ↓出力される結果の例↓ -----

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

----- ↑出力される結果の例↑ -----

この問題を解くヒント

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

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

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

1.import文
 1-1. Scannerクラスのインポート
2.Shapeインターフェースの定義
 2-1. calculateAreaメソッドの宣言
3.Rectangleクラスの定義
 3-1. Shapeインターフェースを実装
 3-2. フィールドwidthとheightの定義
 3-3. コンストラクタの定義(widthとheightを受け取る)
 3-4. calculateAreaメソッドの実装(width * heightを返す)
4.Circleクラスの定義
 4-1. Shapeインターフェースを実装
 4-2. フィールドradiusの定義
 4-3. コンストラクタの定義(radiusを受け取る)
 4-4. calculateAreaメソッドの実装(Math.PI * radius * radiusを返す)
5.Mainクラスの定義
 5-1. mainメソッド
  5-1-1. Scannerオブジェクトの作成
  5-1-2. ユーザーに長方形の幅と高さを入力させる
  5-1-3. Rectangleオブジェクトの作成と面積の計算
  5-1-4. 長方形の面積を表示
  5-1-5. ユーザーに円の半径を入力させる
  5-1-6. Circleオブジェクトの作成と面積の計算
  5-1-7. 円の面積を表示
  5-1-8. Scannerオブジェクトを閉じる

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

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

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 ***ここに面積を計算して返すコードを書いてください***;
    }
}

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

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

    // インターフェースのcalculateAreaメソッドを実装
    @Override
    public double calculateArea() {
        return ***ここに面積を計算して返すコードを書いてください***;
    }
}

// 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 = ***ここにRectangleクラスのオブジェクトを作成するコードを書いてください***;
        System.out.println("長方形の面積: " + rectangle.calculateArea());

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

        // 円の面積を計算
        Shape circle = ***ここにCircleクラスのオブジェクトを作成するコードを書いてください***;
        System.out.println("円の面積: " + circle.calculateArea());

        scanner.close();
    }
}

 

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

解答例

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

正解コードの例

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

********************

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());

        scanner.close();
    }
}

********************

コードの解説

インターフェースは、クラスが実装するべきメソッドの契約を定め、異なるクラスに共通の機能を提供しながら、それぞれのクラスが独自の実装を行うことを可能にする仕組みです。

このコードをブロックごとに解説していきます。

インターフェース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()メソッドを呼び出して、図形の面積を計算して結果を表示します。

まとめ

このコードでは、インターフェースを使うことで、異なるクラスに共通のメソッドcalculateArea()を実装しつつ、クラスごとに異なる実装を提供しています。

インターフェースは、異なるクラスが共通の動作を持ちながらも、それぞれに独自の動作をさせたい場合に非常に有効です。

<<前の問題 問題集Top 次の問題>>

この問題への質問・コメント

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

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






    JAVA練習問題集へ戻る
    トップページへ戻る