Javaプログラミング基礎

演習問題

解答は

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

問題1 (Basic)

問題1-1

「携帯電話」-「カメラ付き携帯」のような継承関係にある2つのクラスを、 身の周りから探しなさい。また、継承関係にあると判断した理由も答えなさい。

解答は文章でファイル Q1-1.txt に記述すること。

問題1-2

「学校」-「大学」-「私立大学」のような関係は、大学は学校としての性質を 受け継ぎ、私立大学は大学としての性質を受け継いでいることから、 3階層の継承関係と考えることができる。 身の周りから3階層にわたるクラスの継承関係を探しなさい。 また、そう判断した理由も答えなさい。

解答は文章でファイル Q1-2.txt に記述すること。

問題2 (Basic)

「人」を表す Person クラスを考える。 人間といっても様々な人がいる、ということで次のような人間を考えてみる。

年齢を聞いたときの答えとして

という3種類の人間を考えよう。

このような人々をクラスで表現することを考える。 まずは、共通部分をまとめた基底クラス Person を定義する。

class Person {
    protected String name;
    protected int age;

    public Person() { }

    public Person(String n, int a) {
        name = n;
        age = a;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return 0;
    }
}

上のように、年齢を求める getAge メソッドは、とりあえず意味のない値 (0) を返すことにしておく。

このクラス Person を継承し、 正直な年齢を答えるクラス HonestPerson と、 大体の年齢を答えるクラス VaguePerson と、 さばを読んだ年齢を答えるクラス Lier を作成しなさい。 継承を行った各サブクラスで getAge メソッドをオーバライドし、 年齢を答えるように作る。

大体の年齢とは 10 歳単位で四捨五入した歳とする。 int 型での計算であれば次の式で求めることができる。

((age + 5) / 10) * 10

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

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

プログラムの大まかな構成および main メソッドの例は以下のとおりである。

class VariousPeople {
    public static void main(String[] args) {
        HonestPerson maurice = new HonestPerson("Maurice White", 24);
        VaguePerson philip = new VaguePerson("Philip Bailey", 32);
        Lier jonny = new Lier("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();
    }
}

// 基底クラス Person
class Person {
    protected string name;
    protected int age;

    public Person() { }

    public Person(String n, int a) {
        name = n;
        age = a;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return 0;
    }
}

// 正直な年齢を答える人
class HonestPerson .....
    // コンストラクタは継承されないので定義する 
    public HonestPerson(String n, int a) {
        ..... // (super を使うと良い)
    }

    // getAge メソッドをオーバライド
    public int getAge() {
        ....
    }
}

// あいまいな年齢を答える人
class VaguePerson .....
    .....


// さばを読んだ年齢を答える人
class Lier ....
....

問題3 (Standard)

問題3-1

財布を表すクラス Wallet を定義しなさい。 財布にはお金以外にカード類や領収書などを収納する機能があるが、 ここではお金を収納する機能にのみ着目する。

クラス Wallet には、少なくとも以下の属性、メソッドがあるものとする。

クラス Wallet の使用例と実行例は以下の通り。

class PersonWithWallet1 {
    public static void main(String[] args) {
        System.out.println("財布: ");
        Wallet wallet = new Wallet();
        wallet.put(1000);
        wallet.printAmount();
        wallet.get(10000);
	wallet.printAmount();
    }
}

class Wallet {
    // ここを考える
}

実行例:

$ java PersonWithWallet1
財布: 
1000 入れました。
-----> 中身は 1000 です。
10000 取り出します。
-----> 10000 もありません。1000 だけ取り出します。
-----> 中身は 0 です。
$

問題3-2

ブタ(pig)の形をした貯金箱(piggy bank)を定義しなさい。 この貯金箱は、お金を収納できるので財布の一種と考えることができるが、 お金を一部だけ取り出すことはできず、壊して全額取り出すことしかできない。

この貯金箱を表すクラス PiggyBank を、 財布を表すクラス Wallet を継承させて作成しなさい。 その際、Wallet に実装されているが Wallet とは動作の異なるメソッドを、 オーバライドして作成することになる。 例えば、get は常に 0 を返すメソッドにする必要がある。

余力のある人は、一度壊したら (= getAll したら)、 それ以降は put もできないようにすること。


class PersonWithWallet2 {
    public static void main(String[] args) {
        System.out.println("財布: ");
        Wallet wallet = new Wallet();
        System.out.println("1000 入れます。");
        wallet.put(1000);
	wallet.printAmount();
        System.out.println("10000 取り出します。");
        wallet.get(10000);
	wallet.printAmount();
        System.out.println();
        
        System.out.println("貯金箱: ");
        PiggyBank piggyBank = new PiggyBank();
        System.out.println("1000 入れます。");
        piggyBank.put(1000);
        piggyBank.printAmount();
        System.out.println("500 取り出します。");
        piggyBank.get(500);
        piggyBank.printAmount();
        System.out.println("すべて取り出します。");
        piggyBank.getAll();
	piggyBank.printAmount();
        System.out.println("10000 入れます");
        piggyBank.put(10000);
    }
}

class Wallet {
    // ここは問題3-1のものをそのまま使う
}

class PiggyBank extends Wallet {
    // ここを考える
}

実行例:

$ java PersonWithWallet2
財布: 
1000 入れます。
-----> 中身は 1000 です。
10000 取り出します。
-----> 10000 もありません。1000 だけ取り出します。
-----> 中身は 0 です。

貯金箱: 
1000 入れます。
-----> 中身は 1000 です。
500 取り出します。
-----> 一部だけ取り出すことはできません。
-----> 中身は 1000 です。
すべて取り出します。
-----> 貯金箱を壊して全額取り出しました。この貯金箱はもう使えません。
-----> 中身は 0 です。
10000 入れます。
-----> 壊してしまったのでお金を入れられません。
$

問題4 (Standard)

会社の従業員の給与計算を行うプログラムを考えなさい。

従業員には正社員とアルバイトの2つの職種があるとし、 正社員とアルバイトでは給与体系に以下のような違いがあるとする。

このような給与計算を行う「正社員」のクラスと、 「アルバイト」のクラスを考えると、 両者には共通した性質があると考えることができる。 そこで、次のような方針でプログラムを設計しよう。

以上の考え方に基づき、クラス Employee, Staff, Arbeit を定義し、 正社員とアルバイトの1ヶ月の給料を計算するプログラムを書きなさい。 (ファイル名 Employment.java) プログラムの大枠は次のとおり。

class Employment {
    public static void main(String[] args) {
	Staff medio = new Staff("電大 メディ男");
	Arbeit denko = new Arbeit("電大 デン子");

	printSalary(medio);
	printSalary(denko);
    }

    private static void printSalary( ........ ) {
	// 9時から18時まで24日間働いたときの1ヶ月の給料を表示
        System.out.println(person.getName() + " さんの1ヶ月の給料は " +
			   person.getMonthlySalary(9,18,24) + " 円です。");
    }
}

class Employee {
    private String name;

    public Employee(String n) {
	name = n;
    }

    public String getName() {
	return name;
    }

    // 始業時間、終業時間、労働日数から1ヶ月の給料を計算
    public int getMonthlySalary(int from, int to, int days) {
	// 正社員とアルバイトで計算方法が異なるため、
	// とりあえず 0 を返すようにしておく
	return 0;
    }
}


// 正社員を表わすクラス Staff の定義をここに書く
class Staff ...........
    ........


// アルバイトを表わすクラス Arbeit の定義をここに書く
class Arbeit ...........
    ........

問題5 (Advanced)

問題5-1

CDとDVD Videoについて考えよう。 CDには音楽作品(Music)が複数記録されており、 DVD Videoには映像作品(Movie)が複数記録されている。

ここで、音楽作品と映像作品の性質を考えると、 どちらも作者(演奏家)と題名を持つ似たような性質のものだと考えられる。 そこで、まず音楽作品と映像作品に共通する性質を抽出し スーパクラスとして「コンテンツ(Content)」を定義し、 コンテンツを継承することで「音楽」と 「映像」のクラスを定義することが考えられる。 ただし、映像作品には、言語音声の種類や字幕、 視聴可能なリージョン(国や地域)などの情報が含まれているとする。

以上のような考え方に基づき、 コンテンツ (クラス Content)、 音楽 (クラス Music)、 映像 (クラス Movie) を作成しなさい。

ファイル名は VariousMedia.java とし、適当な main メソッドを書くこと。

問題5-2

上で定義したコンテンツが複数記録できるディスク (クラス Disc) を作成し、 この Disc クラスを継承する形で CD (クラス CompactDisc) 、DVD Video (クラス DVDVideo) を作成しなさい。

ファイル名は CDAndDVD.java とし、適当な main メソッドを書くこと。

問題5-3

上で定義した DVD Video が視聴できる DVD プレーヤを表すクラス DVDPlayer を定義しなさい。 DVD プレーヤでは DVD Video の再生だけではなく CD も演奏可能なものとすること。

視聴や演奏をすると言っても、 実際に本物の動画や音楽を再生するわけではなく、 "Now playing: 題名 (作者)" のように、 再生の様子を表示することにする。

ファイル名は DVDWatcher.java とする。 適当な映像作品を題材とした DVD Video および、 適当な音楽作品を題材とした CD を作成し、 再生できる様子を main メソッドに書くこと。

問題6 (Advanced)

複数のクラスに共通する性質を記述した 基底クラスを定義し、継承させることが有効な事柄を取り上げ、 プログラムとしなさい。適当な main メソッドも用意すること。 ファイル名は BaseClass.java とする。