[小西ホームページ]   [目次・索引]   [前の授業]   [次の授業]

コンピュータIIIB(Javaアルゴリズム)第11回

目次 索引
11.1 継承(1)
11.1.1 継承とは
11.1.2 継承の例
11.2 演習11
11.3 レポート課題
11.4 参考文献

11.1 継承(1)

11.1.1 継承とは

11.1.2 継承の例


h2 継承 toc-inheritance

h3 継承とは toc-what-is-inheritance

オブジェクト指向プログラミングにおけるオブジェクトとは、
処理対象の性質や機能をモデル化した、
変数、関数、および手続きの構造であることは、
以前説明した通りです。
オブジェクトを表すデータ型はクラスと呼ばれ、
クラスに属するオブジェクトはインスタンスと呼ばれました。
また、オブジェクトの変数はインスタンス変数と呼ばれ、
オブジェクトの関数と手続きはメソッドと呼ばれました。

ここで、オブジェクトの例として腕時計を考えます。
一般的な腕時計には時針と分針があります。
腕時計の性質は、何時何分を覚えていることであり、
腕時計の機能は、何時何分が読み取れることと、何時何分が変更できることです。
腕時計を表すクラスを Watch とします。
このクラスでは、何時何分を覚えるインスタンス変数が用意され、
何時何分を読み取るメソッドと、何時何分を変更するメソッドが定義されます。

腕時計の中には秒針を持つものもあります。
秒針を持つ腕時計をクラス ThreeHandWatch で表します。
秒針を持つ腕時計の性質と機能は、一般的な腕時計に似ています。
違いは、何秒に関する部分が追加されることです。
したがって、クラス ThreeHandWatch のインスタンス変数とメソッドは、
クラス Watch のインスタンス変数とメソッドと似たように定義されます。

性質と機能が似る理由は、秒針を持つ腕時計は腕時計の特殊なものであり、
特殊なものは一般的なものから多くの性質と機能を受け継ぐ傾向があるからです。
もし、一般的なものから性質と機能を受け継ぐ仕組みがあれば、
同じことを何度も書かずに済むようになります。

オブジェクト指向プログラミングでは、
クラスの間に階層関係を与えることができます。
この関係は、下位のクラスは上位のクラスより特殊なことを意味します。
上位のクラスは下位のクラスより一般的なことを意味するとも言えます。
上位のクラスは
index スーパークラス superclass すうはあくらす
と呼ばれ、下位のクラスは
index サブクラス subclass さふくらす
と呼ばれます。

サブクラスは、
スーパークラスのインスタンス変数とメソッドを受け継ぎます。
この、インスタンス変数とメソッドを受け継ぐ仕組みは、
index 継承 inheritance けいしよう
と呼ばれます。
継承を利用しますと、サブクラスを定義するときは、
スーパークラスとの違いのみを書けば済みます。
クラス ThreeHandWatch の場合ですと、
クラス Watch と同じことを再び書くのではなく、
クラス Watch をスーパークラスにし、
何秒に関する部分のみを書くのです。

一つのクラスのスーパークラスが一つに限られる継承の仕組みは、
index 単一継承 single inheritance たんいつけいしよう
と呼ばれます。
複数のスーパークラスが許される継承の仕組みは、
index 多重継承 multiple inheritance たしゆうけいしよう
と呼ばれます。
Java は単一継承のプログラミング言語です。

単一継承であっても、
一つのクラスのサブクラスは複数個になり得ます。
例えば、今日は何日かが分かる表示窓の付いた腕時計を考えます。
このクラスの名前を DayDisplayWatch とします。
このクラスは、何日に関する部分以外はクラス Watch と同じです。
したがって、クラス Watch をスーパークラスにし、
何日に関する部分のみを書けば、このクラスの定義が完成します。
クラス ThreeHandWatch もクラス DayDisplayWatch も、
クラス Watch のサブクラスです。

継承は何段階も行えます。
例として、何月何日という表示窓の付いた腕時計 CalendarWatch を定義します。
クラス Watch をスーパークラスにしても良いですが、
クラス DayDisplayWatch をスーパークラスにしたほうがより良いです。
なぜならば、クラス Watch からは何時何分に関する部分が継承され、
クラス DayDisplayWatch からは何日に関する部分が継承されるからです。
このクラスでは、何月に関する部分のみを書けば済みます。

以上の 4 つのクラスの階層関係を図で表しますと、
次のようになります。

             Watch
               |
       +-------+-------+
       |               |
ThreeHandWatch  DayDisplayWatch
                       |
                       +-------+
                               |
                         CalendarWatch

h3 継承の例 toc-inheritance-examples

それでは、クラス Watch から定義していきます。
何時何分を覚えるために、インスタンス変数 hour と minute を用意します。
何時何分を読み取るために、メソッド getHour と getMinute を定義し、
何時何分を変更するために、メソッド setHour と setMinute を定義します。

Watch.java

class Watch {
    int hour, minute;
    int getHour () {
        return this.hour;
    }
    int getMinute () {
        return this.minute;
    }
    void setHour (int hour) {
        this.hour = hour;
    }
    void setMinute (int minute) {
        this.minute = minute;
    }
}

WatchMain.java

class WatchMain {
    public static void main (String[] args) {
        Watch w = new Watch();
        w.setHour(13);
        w.setMinute(15);
        System.out.print(w.getHour());
        System.out.print(":" + w.getMinute());
        System.out.println();
    }
}

b04a001@AsiaA1:~/comp3b% java WatchMain
13:15
b04a001@AsiaA1:~/comp3b%

もし、継承を使わずにクラス ThreeHandWatch を定義しますと、
次のようになります。

ThreeHandWatch.java

class ThreeHandWatch {
    int hour, minute, second;
    int getHour () {
        return this.hour;
    }
    int getMinute () {
        return this.minute;
    }
    int getSecond () {
        return this.second;
    }
    void setHour (int hour) {
        this.hour = hour;
    }
    void setMinute (int minute) {
        this.minute = minute;
    }
    void setSecond (int second) {
        this.second = second;
    }
}

WatchMain.java (第 2 版)

class WatchMain {
    public static void main (String[] args) {
        ThreeHandWatch w = new ThreeHandWatch();
        w.setHour(13);
        w.setMinute(15);
        w.setSecond(30);
        System.out.print(w.getHour());
        System.out.print(":" + w.getMinute());
        System.out.print(":" + w.getSecond());
        System.out.println();
    }
}

b04a001@AsiaA1:~/comp3b% java WatchMain
13:15:30
b04a001@AsiaA1:~/comp3b%

確かに、クラス ThreeHandWatch の定義の半分以上は、
クラス Watch の定義と同じです。
継承を利用して、インスタンス変数とメソッドを受け継ぐべきです。

Java では、クラス A を定義するときに、
クラス B をクラス A のスーパークラスにすることを、

    class A extends B {
        ...
    }

と書きます。

では、クラス ThreeHandWatch の定義を書き直します。
クラス ThreeHandWatch とクラス Watch の違いは、
インスタンス変数 second が追加されている点と、
メソッド getSecond と setSecond が追加されている点です。
したがって、それらのみを定義します。

ThreeHandWatch.java (第 2 版)

class ThreeHandWatch extends Watch {
    int second;
    int getSecond () {
        return this.second;
    }
    void setSecond (int second) {
        this.second = second;
    }
}

WatchMain.java (第 2 版再び)

class WatchMain {
    public static void main (String[] args) {
        ThreeHandWatch w = new ThreeHandWatch();
        w.setHour(13);
        w.setMinute(15);
        w.setSecond(30);
        System.out.print(w.getHour());
        System.out.print(":" + w.getMinute());
        System.out.print(":" + w.getSecond());
        System.out.println();
    }
}

b04a001@AsiaA1:~/comp3b% java WatchMain
13:15:30
b04a001@AsiaA1:~/comp3b%

メソッド setHour などが、
クラス ThreeHandWatch で定義されていないのにも関わらず、
呼び出せることに注意してください。

クラス DayDisplayWatch は次のように定義されます。

class DayDisplayWatch extends Watch {
    int day;
    int getDay () {
        return this.day;
    }
    void setDay (int day) {
        this.day = day;
    }
}

クラス CalendarWatch は次のように定義されます。

class CalendarWatch extends DayDisplayWatch {
    int month;
    int getMonth () {
        return this.month;
    }
    void setMonth (int month) {
        this.month = month;
    }
}

WatchMain.java (第 3 版)

class WatchMain {
    public static void main (String[] args) {
        CalendarWatch w = new CalendarWatch();
        w.setMonth(12);
        w.setDay(10);
        w.setHour(13);
        w.setMinute(15);
        System.out.print(w.getMonth());
        System.out.print("/" + w.getDay());
        System.out.print(" " + w.getHour());
        System.out.print(":" + w.getMinute());
        System.out.println();
    }
}

b04a001@AsiaA1:~/comp3b% java WatchMain
12/10 13:15
b04a001@AsiaA1:~/comp3b%

確かに、クラス CalendarWatch は、
クラス Watch とクラス DayDisplayWatch を継承しています。

h2 演習 11 toc-exercises

コイン・ランドリーの洗濯機について、プログラムを作成してください。

この洗濯機は、100 円玉が 2 枚投入されますと、洗濯を行うものとします。
洗濯機を表すクラスは、WashingMachine とします。
100 円玉を 1 枚投入することは、メソッド insertCoin で表すことにします。
洗濯が行われたことは、画面に "It washed." と出力することで表します。
一度洗濯しますと、また洗濯するには、100 円玉が 2 枚必要です。

洗濯機の特殊なものとして、取り消しボタン付きの洗濯機を考えます。
これは、100 円玉を 1 枚投入した後で、取り消しボタンを押しますと、
100 円玉が返却口に落ちてくるものです。
取り消しボタン付きの洗濯機のクラスは、CancelButtonWashingMachine とします。
このクラスは、クラス WashingMachine のサブクラスとします。
取り消しボタンを押すことは、メソッド pushCancelButton で表すことにします。
取り消されたことは、画面に "A coin dropped." と出力することで表します。
100 円玉が投入されていなければ、取り消しボタンを押しても何も起こりません。
また、一度取り消しますと、また洗濯するには、100 円玉が 2 枚必要です。

今、取り消しボタン付きの洗濯機の前にいるとします。
いきなり取り消しボタンを押しても何も起こりませんでしたが、
100 円玉を 1 枚投入し、取り消しボタンを押しましたら、
100 円玉が落ちてきました。
その後、100 円玉を 2 枚投入したら、洗濯が始まりました。
洗濯が終わってから、100 円玉を 1 枚投入し、取り消しボタンを押しましたら、
100 円玉が落ちてきました。
このことを、プログラムを作成して実現してください。

メイン・プログラムは以下の通りとし、
クラス WashingMachine と CancelButtonWashingMachine の
定義プログラムを自作してください。

class WashingMachineMain {
    public static void main (String[] args) {
        CancelButtonWashingMachine m;
        m = new CancelButtonWashingMachine();
        m.pushCancelButton();
        m.insertCoin();
        m.pushCancelButton();
        m.insertCoin();
        m.insertCoin();
        m.insertCoin();
        m.pushCancelButton();
    }
}

b04a001@AsiaA1:~/comp3b% java WashingMachineMain
A coin dropped.
It washed.
A coin dropped.
b04a001@AsiaA1:~/comp3b%

11.2 演習11


11.3 レポート課題

今日の演習11の答案をkonishi@twcu.ac.jpあてにメールで送ってください。 メールには、学生番号、氏名、科目名、授業日(12月10日)を明記してください。


11.4 参考文献


[小西ホームページ]   [目次・索引]   [前の授業]   [次の授業]

2004年12月10日更新
konishi@twcu.ac.jp
Copyright (C) 2004 Zenjiro Konishi. All rights reserved.