未来エンジニア養成所Blog

月単価180万以上のプログラミング講師がプログラミングを皆に楽しんでもらうための情報をお届けします。

【Java】オブジェクト指向の応用問題3-3

title


問題3-3

デジカメを表現するDigitalCameraクラスと、画像を表現するPictureクラスを作成してください。


また、デジカメクラスを使用するArrayListNormalPracticeクラスのmainメソッドは完成しています。
(変更は禁止です)


【Pictureクラス】

  1. 被写体を表現するインスタンスフィールドtarget(String型)を定義します。

  2. 被写体(String型)を引数に受け取るコンストラクタを定義します。
    引数で受け取った値を、インスタンスフィールドに格納してください。

  3. オブジェクトの説明文を文字列として戻すためのtoStringメソッドをオーバーライドしてください。
    戻り値として返す値は「○○の画像」という文字列です。


【DigitalCameraクラス】

  1. 撮影した画像を管理するArrayList型のメモリインスタンスフィールドmemoryを定義します。

  2. 引数なしコンストラクタを定義します。
    その中で、メモリインスタンスフィールドのオブジェクトを生成します。

  3. 画像撮影メソッドtakePictureを定義します。
    引数は被写体(String型)で、戻り値はありません。
    「○○を撮影しました」と出力した後にメモリオブジェクトに画像オブジェクトを登録します。

  4. 画像一覧表示メソッドshowPicturesを定義します。
    引数・戻り値はなしです。
    まず「★☆ 画像一覧 ☆★」と出力し、拡張for文を用いて画像の情報を順に出力します。

  5. 保存画像数取得メソッドgetPictureCountを定義します。
    引数はなしで、戻り値は保存数(int型)です。
    メモリオブジェクトに格納されている画像オブジェクトの個数を戻り値として返します。

  6. 画像全消去メソッドclearMemoryを定義します。
    引数・戻り値はなしです。
    「すべての画像を消去しました」と出力し、メモリオブジェクトに格納されているすべての画像オブジェクトをクリアします。


【実行結果】

子猫を撮影しました。
ランチを撮影しました。
カプチーノを撮影しました。
赤ちゃんを撮影しました。
ツーショットを撮影しました。

現在の撮影枚数:5

★☆ 画像一覧 ☆★
子猫の画像
ランチの画像
カプチーノの画像
赤ちゃんの画像
ツーショットの画像

すべての画像を消去しました

現在の撮影枚数:0


【ArrayListNormalPractice.java】

public class ArrayListNormalPractice {
    public static void main(String[] args) {

        // デジカメオブジェクトの宣言と生成
        DigitalCamera myCamera = new DigitalCamera();

        // デジカメにて撮影
        myCamera.takePicture("子猫");
        myCamera.takePicture("ランチ");
        myCamera.takePicture("カプチーノ");
        myCamera.takePicture("赤ちゃん");
        myCamera.takePicture("ツーショット");

        System.out.println();

        // 撮影画像数の確認
        System.out.println("現在の撮影枚数:" + myCamera.getPictureCount());

        System.out.println();

        // 画像の閲覧
        myCamera.showPictures();

        System.out.println();

        // 画像ファイルのクリア
        myCamera.clearMemory();

        System.out.println();

        // 撮影画像数の再確認
        System.out.println("現在の撮影枚数:" + myCamera.getPictureCount());

    }
}


// ここにデジカメクラスを作成してください


// ここに画像クラスを作成してください


解答例

【ArrayListNormalPractice.java】

import java.util.ArrayList;

public class ArrayListNormalPractice {
    public static void main(String[] args) {

        // デジカメオブジェクトの宣言と生成
        DigitalCamera myCamera = new DigitalCamera();

        // デジカメにて撮影
        myCamera.takePicture("子猫");
        myCamera.takePicture("ランチ");
        myCamera.takePicture("カプチーノ");
        myCamera.takePicture("赤ちゃん");
        myCamera.takePicture("ツーショット");

        System.out.println();

        // 撮影画像数の確認
        System.out.println("現在の撮影枚数:" + myCamera.getPictureCount());

        System.out.println();

        // 画像の閲覧
        myCamera.showPictures();

        System.out.println();

        // 画像ファイルのクリア
        myCamera.clearMemory();

        System.out.println();

        // 撮影画像数の再確認
        System.out.println("現在の撮影枚数:" + myCamera.getPictureCount());

    }
}

// デジカメクラス
class DigitalCamera {

    // メモリフィールド
    private ArrayList<Picture> memory;

    // コンストラクタ
    public DigitalCamera() {
        memory = new ArrayList<Picture>();
    }

    // 画像撮影メソッド
    public void takePicture(String target) {
        System.out.println(target + "を撮影しました。");
        memory.add(new Picture(target));
    }

    // 画像一覧表示メソッド
    public void showPictures() {
        System.out.println("★☆ 画像一覧 ☆★");

        for(Picture picture : memory) {
            System.out.println(picture);
        }
    }

    // 保存画像数取得メソッド
    public int getPictureCount() {
        return memory.size();
    }

    // 画像全消去メソッド
    public void clearMemory() {
        memory.clear();
        System.out.println("すべての画像を消去しました");
    }
}

// 画像クラス
class Picture {

    // 被写体フィールド
    private String target;

    // コンストラクタ
    public Picture(String target) {
        this.target = target;
    }

    @Override
    public String toString() {
        return target + "の画像";
    }
}


解説

今回は、ArrayListクラスを利用したデジカメクラスを作成します。

「あるクラスを活かして別のクラスを作成する」と聞くと、「継承」をイメージする人もいるかもしれません。

しかし、クラスの再利用で「継承」を使用するのは、どちらかと言うと「最終手段」に近いです。


今回のデジカメクラスは、ArrayListオブジェクトをインスタンスフィールドとして保持して利用しています。

この発送を「コンポジション」と言います。


クラスの再利用で「継承」を使うのはリスクが大きいので、できるだけ「コンポジション」を利用しましょう。



今回の問題は、いきなり引っかけがありました。

引っ掛かった人も多かったでしょう。


ArrayListクラスはjava.utilパッケージのクラスのなので通常はインポート文を記述しますが、それが書いてありません。

インポート文はクラス定義の上にしか記述できませんので注意してください。



デジカメクラスが唯一持っているインスタンスフィールドmemoryはArrayList型です。

ジェネリックスを用いて型パラメータPictureを指定することで、このArrayListオブジェクトにはPictureオブジェクトしか追加できなくなるわけです。

しかし、takePictureメソッドを次のように記述して、コンパイルが通らなかった人も多かったでしょう。

// 画像撮影メソッド(コンパイルエラー)
public void takePicture(String target) {
    System.out.println(target + "を撮影しました。");
    memory.add(target);
}



今回のmemoryインスタンスフィールドはArrayList型なので、ジェネリックスが反映されてaddメソッドの引数はPicture型になります。

takePictureメソッドの引数targetはString型なのでコンパイルエラーとなります。


次のように、memoryフィールドに追加するタイミングでPictureオブジェクトを生成すればOKです。

// 画像撮影メソッド
public void takePicture(String target) {
    System.out.println(target + "を撮影しました。");
    memory.add(new Picture(target));
}



Pictureクラスは被写体を表す文字列をラップするだけのシンプルなクラスです。

toStringメソッドをオーバーライドしているので、画像情報を出力するshowPicturesメソッドでは、次のようにPictureオブジェクトをそのままSystem.out.printlnメソッドに渡すだけでOKです。

// 画像一覧表示メソッド
public void showPictures() {
    System.out.println("★☆ 画像一覧 ☆★");
    for(Picture picture : memory) {
        System.out.println(picture);
    }
}



ちなみに、デジカメクラスのメソッドは、結局ArrayListオブジェクトメソッドを呼び出して仕事を任せているだけです。

この発想を「委譲(デリゲーション)」と言います。


参考図書



LINE公式アカウント

仕事が辛くてたまらない人生が、仕事が楽しくてたまらない人生に変わります。
【登録いただいた人全員に、無料キャリア相談プレゼント中!】


LineOfficial

友だち追加