Javaプログラミング基礎

演習問題 (中級〜上級)

解答は

に提出しなさい。ソースファイル (〜.java) のみを提出。 提出は gFTP 等の ftp ソフトを用いて行う。

問題1

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

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

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

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

class VariousPeople {
    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();
    }
}

......

問題2

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

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

スーパの商品に共通する「値段を求めることができる」 ということを 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)

問題3

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

class Music {
    private String name;
    private String musician;
    public Music(String musicName, String musicianName) {
        name = musicName;
        musician = musicianName;
    }
    public String getName() {
        return name;
    }
    public String getMusician() {
        return musician;
    }
}

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].getMusician());
        }
    }
}

クラス 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 Music ....

    // Comparable インタフェースを実装した 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");

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

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

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

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