コンピュータ基礎および演習II

演習問題

解答は

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

問題1

以下に挙げる A → B の各組み合わせについて、その関係とそう判断した理由を述べなさい。 解答は文章でファイル Q1.txt に記述すること。

  1. A:「書籍」→ B:「雑誌」
  2. A:「雑誌」→ B:「広告ページ」
  3. A:「衣類」→ B:「コート類」
  4. A:「タワー」→ B:「東京タワー」
  5. A:「大学」→ B:「学部」
  6. A:「パソコン」→ B:「内蔵ハードディスク」
  7. A:「自動車メーカー」→ B:「BMW社」

関係の選択肢:

注: 「衣類」は着るもの全般を表す言葉で、衣服の種類、という意味ではない。

ヒント1: 「is-a」という言葉にこだわると、 クラスとインスタンスの関係まで is-a の関係に見えてくるので注意すること。 惑わされる人は、先にクラスとインスタンスの関係かどうかを判断するとよい。 「A → B」で A がクラスの場合、B がクラス A の具体例であれば、 「A → B」はクラスとインスタンスの関係である。

ヒント2: ここで言う「has-a の関係」とは、クラスとクラスの関係であることに注意すること。

問題2

円柱(cylinder)を表すクラスを定義しなさい。 クラス名は Cylinder とする。 円柱の形状は、底面の半径(radius)と高さ(height)により定まる。 空間上の位置は考慮しなくてよい。

問題2-1

クラス Cylinder には、少なくとも以下のメソッドを実装しなさい。

また、底面の半径と円柱の高さを引数にとるコンストラクタを実装しなさい。

アクセスに関しては、以下の方針で設計しなさい。

なお、数値はすべて整数でよい。 円周率は3でよいが、Math.PI とするとπにもっとも近い double 値が得られる(参考)。

ファイル名は CylinderProperties1.java とする。 クラス CylinderProperties1 は次のようになる。

class CylinderProperties1 {
    public static void main(String[] args) {
	int radius = 5;
	int height = 10;
	Cylinder cylinder = new Cylinder(radius, height);
	System.out.println("円柱(半径=" + radius + ", 高さ=" + height + ")の");
	System.out.println(" 体積は" + cylinder.volume());
	System.out.println(" 表面積は" + cylinder.surfaceArea());
    }
}

問題2-2

円柱は、底面と側面からできている。 つまり、円柱と底面、円柱と側面の関係は has-a の関係である。 底面は円(circle)であり、側面は長方形(rectangle)である。 クラス Circle とクラス Rectangle を定義し、 これらを属性として持つようにクラス Cylinder を変更しなさい。 なお、Circle, Rectangle についてもアクセス制限に気を配ること。

クラス Circle に面積と円周、 クラス Rectangle に面積を求めるメソッドを実装し、 クラス Cylinder で体積や表面積を求めるときにそれらを用いること。

ファイル名は CylinderProperties2.java とする。 クラス CylinderProperties2 は次のようになる。

class CylinderProperties2 {
    public static void main(String[] args) {
	int radius = 5;
	int height = 10;
	Cylinder cylinder = new Cylinder(radius, height);
	System.out.println("円柱(半径=" + radius + ", 高さ=" + height + ")の");
	System.out.println(" 体積は" + cylinder.volume());
	System.out.println(" 表面積は" + cylinder.surfaceArea());
    }
}

円と長方形を生成しておいてクラス Cylinder のコンストラクタに渡すことも考えられなくはないが、 クラス Cylinder 内部でクラス Circle とクラス Rectangle のインスタンスを生成して用いることにより、 クラス Circle やクラス Rectangle の使い方を知らない人でもクラス Cylinder が使えるようになる。

注意: new によるインスタンスの生成はコンストラクタかメソッド内で行うこと。 属性を宣言する際にインスタンスを生成し代入することはできない。

問題3

あなたはこの冬休み、念願の車の購入に踏み切ることにした。信号が青に変わった時に先頭で飛び出さなければ気が済まない性格なため、加速最優先で車選びをすることにした(予算の範囲内で)。

問題3-1

車は数多くの部品から成り立っているが、ここでは大雑把に、 車(car)は車体(body)とエンジン(engine)からなるものとする。 車クラス Car、車体クラス Body、エンジンクラス Engine を定義しなさい。 それぞれ、重量を求めるメソッド getWeight() を実装すること。 クラス Body のインスタンスの生成はクラス Car のコンストラクタ内で行なうこと。 クラス Engine のインスタンスは外部で生成し、クラス Car のインスタンスに渡すこと。

問題3-2

車の加速のよさを判断する際に参考になる指標として、 パワーウエイトレシオ(Power-to-Weight Ratio; 車重/エンジンの出力)がある。 エンジンの出力が大きくても車体が重ければ加速は鈍くなる。 エンジンの出力 1 [kW] 当たりの車重が軽いほど、つまり、 パワーウエイトレシオの値が小さいほど加速がよいと判断できる。

クラス Engine に出力を返すメソッド getPower() を、 クラス Car にパワーウエイトレシオを返すメソッド getPowerToWeightRatio() を実装しなさい。

以下のように、エンジンを積み替えることができるようにすること。

class Driver {
    public static void main(String[] args) {
        Engine engine1 = new Engine( 80, 300);  //  80[kW], 300[kg]
        Engine engine2 = new Engine(100, 400);  // 100[kW], 400[kg]
        Car car = new Car(1000);                // 1000[kg] (body)
	car.setEngine(engine1);
	System.out.println(
	    "エンジン1搭載時のパワーウエイトレシオ: " + car.getPowerToWeightRatio());
	car.setEngine(engine2);
	System.out.println(
	    "エンジン2搭載時のパワーウエイトレシオ: " + car.getPowerToWeightRatio());
}

この問題の提出ファイルのファイル名は Driver.java とする。

問題4

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

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

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

問題5

余力のある人だけ取り組む問題。

あなたは、携帯音楽プレーヤにダウンロードした曲が増えすぎて、 どんな曲が入っているかもよくわからなくなってきたので、 曲の情報を 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 インタフェースを実装している必要がある。 ( 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;
    ....
}