Javaプログラミング基礎 演習問題

解答は

に提出しなさい。クラスファイル (〜.class) は提出しなくてよい。 提出には gFTP 等の ftp ソフトを用いること。

問題1 (Basic)

以下のやり方はプログラムの設計方法として正しいか否かを判断しなさい。 ○×で答え、その理由を述べること。 ファイル名は Q1.txt とする。

  1. 大学には必ず学部があるので、学部クラスを継承する形で大学クラスをつくった。
  2. 大学にも高校にも入試があり、出願手続きなどの手順は似通っている。そこで入試インタフェースを定義して、大学クラスと高校クラスの両方にそのインタフェースを実装した。
  3. HDD(ハードディスクドライブ)も光学ドライブもドライブという点では共通なので、まずドライブクラスをつくり、それをHDDクラスと光学ドライブクラスに継承させた。
  4. ビル建設も橋の建設も鉄骨が重要であることは共通なので、鉄骨クラスを継承し、ビルクラスと橋クラスをつくった。

問題2 (Basic)

今日の例題では2次元の図形としてのインタフェースを表す Shape を定義し、 円と矩形のクラスを定義した。

同様の考え方に基づき、3次元の図形としてのインタフェース ThreeDShapeを定義しなさい。3次元の図形には次のような機能があるとする。

ThreeDShape のインタフェースを実装し、 少なくとも 2 種類の立体図形を表すクラスを作成しなさい。 さらに、クラス SolidFigures に main メソッドを作成し、 表面積や体積を求める様子を書きなさい。 (ファイル名 SolidFigures.java)

問題3 (Standard)

前回の演習問題 で、3つのタイプの人を表わすクラスを作成した。 その際、人の共通の特徴を表すクラスとして基底クラス Person を定義し、 その Person クラスを継承させて、3つのタイプの人を表わすクラスを作成した。

ここでは別の考え方として、基底クラスを定義する代わりに、 「人」であることを表わすような共通のインタフェースを定義することを考える。 正直な年齢を答える人、10歳単位で四捨五入した年齢を答える人、 さばを読んだ年齢を答える人を表わすクラスを、 前述のインタフェースを実装する形で定義しなさい。

さばを読んだ年齢とは、年齢に応じてさばを読み度合を変化させるものとし、 20歳未満であれば実年齢、 20歳以上30歳未満であれば「実年齢-1」、 30歳以 上40歳未満であれば「実年齢-2」、 40歳以上50歳未満であれば「実年齢-3」、 50歳以上であれば「実年齢-4」を答えるものとする。

クラス InterfacedPeople に main メソッドと各自の自己紹介をする introduce メソッドを作成し、正直な人、いい加減な人、さばを読む人のそれぞれに自己 紹介をしてもらう。 (ファイル名 InterfacedPeople.java)

class InterfacedPeople {
    public static void main(String[] args) {
        HonestPerson maurice = new HonestPerson("Maurice White", 24);
        VaguePerson philip = new VaguePerson("Philip Bailey", 32);
        Liar jonny = new Liar("Jonny Graham", 45);

        introduce(maurice);
        introduce(philip);
        introduce(jonny);
    }

    private static void introduce(Person p) {
        System.out.println("Hello, my name is " + p.getName());
        System.out.println("I'm  " + p.getAge() + " years old.");
        System.out.println();
    }
}

interface Person ....

class HonestPerson ....

class VaguePerson ....

class Liar ....

問題4 (Standard)

あなたはスーパの経営者となり、 スーパの業務をコンピュータ化したいと思っているとする。 そこで、商品と、商品の清算をするレジについて考えてみよう。

商品には、肉や魚、果物などがある。 これらの商品には「値段を求めることができる」 という意味では共通のインタフェースを持つことが考えられる。 また、レジでは商品の金額を計算し、 合計やお釣りの計算を行うことができると考えられる。

スーパの商品に共通する「値段を求めることができる」 ということを Java のインタフェースで定義しなさい。 以下のように、インタフェース名は Merchandise とする。

interface Merchandise {
    ......
    値段を計算するためのメソッドの宣言をここに書く
}

次に、肉、魚、果物の3つの商品をクラスとして表わすことを考えよう。 肉、魚、果物、いずれも商品であることは共通であることから、 各商品を、 上で定義したインタフェース Merchandise を実装するクラスとして定義しなさい。 なお、各商品の値段は以下のように計算されるものとする。

以下のように、肉、魚、果物、それぞれを表わすクラスを、 Meat, Fish, Fruit という名前で定義しなさい。

class Meat ............... {
    属性

    値段を計算するメソッド
}

class Fish ............... {
    属性

    値段を計算するメソッド
}

class Fruit ............... {
    属性

    値段を計算するメソッド
}

なお、文字列同士が等しいかの比較をするには、メソッド equals を使うこと。

例:
    if (sweetness.equals("甘い")) {
        変数 sweetness の内容が「甘い」と等しいときの処理をここに書く
    }

さらに、商品の清算を行うレジをクラスとして表わすことを考えよう。 レジでは、各商品の金額を計算し、 払った金額に対してお釣りを計算することができることとする。 以下を参考にし、このようなレジを表わすクラス Register を定義しなさい。

class Register {
    属性
        商品

    メソッド
        清算する商品を登録するメソッド (setMerchandise)

        支払った金額から商品の値段を引いたお釣りを計算するメソッド (check)
}

というわけで、これら考え方に基づき、 商品を清算する様子は以下のメソッド main で 表わすことができる。

class Consumer {
    public static void main(String[] args) {
        Register register = new Register();

        // 300g の肉を買うために 2000 円払う
        System.out.println("300gの肉を買うために2000円払います。");
        Meat steak = new Meat(300);
        register.setMerchandise(steak);
        System.out.println("お釣りは" + register.check(2000) + "円です。");
        System.out.println();

        // 2 切れの魚を買うために 1000 円払う
        System.out.println("2切れの魚を買うために1000円払います。");
	Fish sashimi = new Fish(2);
        register.setMerchandise(sashimi);
        System.out.println("お釣りは" + register.check(1000) + "円です。");
        System.out.println();

        // 甘い果物を買うために 1000 円払う
        System.out.println("甘い果物を買うために1000円払います。");
	Fruit apple = new Fruit("甘い");
        register.setMerchandise(apple);
        System.out.println("お釣りは" + register.check(1000) + "円です。");
    }
}    

ここまで説明した考え方により各インタフェース、クラスを定義し プログラムを完成させなさい。 (ファイル名 Consumer.java)

問題5 (Advanced)

あなたは、携帯音楽プレーヤにダウンロードした曲が増えすぎて、 どんな曲が入っているかもよくわからなくなってきたので、 曲の情報を Java のプログラムで管理することとした。 以下は、以前作成した Music クラスと、 Music クラスのオブジェクトを配列として扱うプログラムである。

class MusicCollector {
    public static void main(String[] args) {
        Music[] song = new Music[4];
        song[0] = new Music("Speak Like A Child", "Herbie Hancock");
        song[1] = new Music("Kung-Fu World Champion", "Hiromi Uehara");
        song[2] = new Music("We're All Alone", "Boz Scaggs");
        song[3] = new Music("Moments Notice", "John Coltrane");

        for(int i = 0; i < song.length; i++) {
            System.out.println(i + ": " + song[i].getName() + " by " +
                               song[i].getArtist());
        }
    }
}

class Music {
    private String name;
    private String artist;
    public Music(String musicName, String artistName) {
        name = musicName;
        artist = artistName;
    }
    public String getName() {
        return name;
    }
    public String getArtist() {
        return artist;
    }
}

クラス MusicCollector では Music オブジェクトの配列を扱っているが、 この配列を曲名のアルファベット順 (辞書順) に並び替えることを考えよう。 Java のクラスライブラリには、配列の探索 (サーチ) や整列 (ソート) を行うための クラス Arrays がある ( Java の API Arrays クラスの説明 参照)。 Arrays クラスの sort メソッドを利用すれば曲名順に並び替えることができる。

sort メソッドによって曲名順に並べ替えを行なうには、 Music クラスが Comparable インタフェースを実装している必要がある。 (Comparable インタフェースも Java のクラスライブラリに用意されている。) ( Java の API Comparable インタフェースの説明 参照)。

Music クラスに Comparable インタフェースを実装するためには、 2 つの Music オブジェクトの間で大小関係が言えるように、 Music クラスに他の Music オブジェクトとの大小を返すメソッド compareTo(Object obj) を作成する必要がある。

compareTo メソッドは、 引数が任意のインスタンスを意味する Object クラスのオブジェクト、 戻り値が int 型とし、 このオブジェクトが比較対象のオブジェクトよりも 辞書順で前に並べるべきであれば -1、等しければ 0、 辞書順で後ろに並ぶべきならば 1 を返すこととする。 (Object クラスは、特に継承関係を明示しなくても全てのクラスのスーパクラスとなるような、 Java にあらかじめ 用意された特別なクラスである。したがって Music クラスも Object クラスの サブクラス (継承関係にある) である。)

ヒント: String クラスの辞書順比較をするメソッドを使うと良い。

以上のことを行い、Comparable インタフェースを実装した Music クラスを作成しなさい。

Comparable インタフェースを実装した Music オブジェクトの配列は、 Arrays.sort(song) として並び替えを行うことができる。 プログラムの例は次のようになる (ファイル名 MusicCollector.java)。

import java.util.Arrays;   // Arrays クラスを使うためのおまじない


class MusicCollector {
    public static void main(String[] args) {
        Music[] song = new Music[4];
        song[0] = new Music("Speak Like A Child", "Herbie Hancock");
        song[1] = new Music("Kung-Fu World Champion", "Hiromi Uehara");
        song[2] = new Music("We're All Alone", "Boz Scaggs");
        song[3] = new Music("Moments Notice", "John Coltrane");

        // song の内容を曲名のアルファベット順に並び替え
        Arrays.sort(song);

        for(int i = 0; i < song.length; i++) {
            System.out.println(i + ": " + song[i].getName() + " by " +
                               song[i].getArtist());
        }
    }
}

class Music ....

    // Comparable インタフェースを実装した Music クラスの内容を書く

}

なお、comapreTo メソッドは Object クラスの引数を受け取ることになるので、 引数の Object オブジェクトを Music オブジェクトとして使うためには以下のように キャストする必要がある。

public int compareTo(Object obj) {
    Music anotherSong = (Music)obj;
    ....
}