[PR] 迷惑メール トップページプロ3ゼミJavaJava入門講座二学期単位10 →3時間目

3時間目 ポリモーフィズム再び

10−3−1.抽象クラス,インタフェースとポリモーフィズムの関係その1

 ポリモーフィズムは、オーバーライドの時に教えましたが、抽象クラス,インタフェースを継承や実装する事 は、メソッドのオーバーライドを行う事と同じです。
その為、抽象クラス,インタフェースとポリモーフィズムは切っても切れない関係です。

 それでは抽象クラスとインタフェースの違いとは何でしょうか。
それは、継承と実装かの違いです。
継承とは「クラス」を受け継ぎ新しいクラスを作成する事です。
実装とは、インタフェースを新しいクラスに「組み込む」事です。

 一般的なJavaの入門では、違いを次のように説明している事が多いです。
継承は1個だけで実装は複数個可能かの違いを説明していますが、それはだけでは有りません。
これは、C++を意識した比較といます(インタフェースでも説明しましたがC++は多重継承が出来る)。

 抽象クラスは、名前の通りクラスを抽象化したクラスです。
ですので、具象メソッドが記述できますし、通常のクラスと同じ継承が出来ます。

 一方のインタフェースは、名前の通りです。
インタフェースを知らない方は以下をご覧下さい。
 インタフェースとは、2つ以上の手順、技術、規格や仕様を意味します。
よって、新しいクラスを作成する時にクラスを継承してインタフェース(複数可能)を実装する事ができま す。
例えば、以下の様に出来ると言う事です。
class クラス名 extends スーパークラス implements インタフェース, インタフェース {
    :
    :
}
インタフェースは、複数実装できるのは、継承と同時でも同じです。

 インタフェースは、クラス同士の手順、技術、規格や仕様を定義しそれをインタフェースとして作成すると 言う事です。
その為、インタフェースには、具象クラスは存在するおかしいのです。
手順、技術、規格や仕様を定義しているだけで各クラスごとの処理の実装は、クラスごとに決められています。

10−3−2.抽象クラス,インタフェースとポリモーフィズムの関係その2

 抽象クラスから継承したサブクラスは、抽象クラスの変数へインスタンス化できます。
又、インタフェースを実装したクラスは、インタフェースの変数へインスタンス化できます。
構文を見せると以下のようになります。
抽象クラス 変数名 = new サブクラス;
インタフェース 変数名 = new 実装クラス;
 但し、それぞれの変数は、宣言した方(抽象クラスまたはインタフェース)で記述されているメソッドしか使 用できません。
なぜこのようにする必要があり、なぜこのような事が出来るのでしょうか。

 抽象クラスにしろインタフェースにしろ必ず、抽象メソッドをオーバーライドしないといけません。
つまり、それは継承や実装したクラスがそのメソッドをすべて持っているからです。
クラスは違うが同じ振る舞いをすることがポリモーフィズムで、クラスのメソッドをそろえておく必要がありま す。

 では、なぜ抽象クラスやインタフェースに継承または実装したクラスがインスタンス化出来るかを説明しま す。
先程も説明したように、抽象クラスやインタフェースを宣言し、サブクラスまたは実装クラスでインスタンス化 すると、抽象クラスやインタフェースの抽象メソッドしかアクセスできない事です。
これは、当然と言えば当然ですね。
つまり、使えるメソッドが宣言側に合わさるわけですし、継承や実装したと言う事は必ずそのメソッドを持って いる事が証明されるので、インスタンス化するクラスは問題なくインスタンス化できます。
又、インタフェースの説明にあるように、まさしくクラス同士の手順、技術、規格や仕様を定義している訳です からこれも当然と言えば当然ですね。

10−3−3.ポリモーフィズムのサンプルプログラム

 ポリモーフィズムをもう一度強調するなら、ポリモーフィズムはクラスによって同じメソッド名でも違う動 作(処理)を行う事です。
ポリモーフィズムは、私たちの生活の中では自然にあることです。
例えば、パソコンの機種名を表示するメソッドがある場合は、機種ごとに違う機種名を表示しなければいけま せん。
ここで、スーパークラスは、コンピュータクラスとして、そのサブクラスとしてパソコンやデスクトップパソ コン又はノートパソコンがあるかもしれません。
それをさらに継承して機種ごとのクラスを作成するとします。
この時に、インタフェースとしてはクラス同士の手順、技術、規格や仕様を定義しますから、型名を表示するメ ソッドを定義し機種ごとのクラスを作成します。
又は、インタフェースの実装は、コンピュータで共通であればコンピュータで実装しても良いかもしれませ ん。
以下のその流れのサンプルプログラムを示します。

Sample10_3_1.java
// コンピュータ
class Computer {

    // CPU名
    private String  cpu;

    // CPU名を返す
    public String getCpu() {

        return cpu;
    }

    // CPU名を設定する
    public void setCpu(String cpu) {

        this.cpu = cpu;
    }
}

// デスクトップパソコン
class DesktopPC extends Computer {

    // ディスプレイ名
    private String  displayName;

    // ディスプレイ名を返す
    public String getDisplayName() {

        return displayName;
    }

    // ディスプレイ名を設定する
    public void setDisplayName(String displayName) {

        this.displayName = displayName;
    }
}

// ノートパソコン
class NotePC extends Computer {

    // バッテリー名
    private String  batteryName;

    // バッテリー名を返す
    public String getBatteryName() {

        return batteryName;
    }

    // バッテリー名を設定する
    public void setBatteryName(String batteryName) {

        this.batteryName = batteryName;
    }
}

// 共通の型
interface TypeCommon {

    // 型名を返す
    public String getTypeName();

    // 型名を設定
    public void setTypeName(String typeName);
}

// A社製ノートブック
class ANotePC extends NotePC implements TypeCommon {

    // 型名
    private String  typeName;
    // USB
    private boolean usb;

    // 型名を返す
    public String getTypeName() {

        return typeName;
    }

    // 型名を設定
    public void setTypeName(String typeName) {

        this.typeName = typeName;
    }

    // USBの使用状況を返す
    public boolean isUsb() {

        return usb;
    }

    // USBの使用状況を設定
    public void setUsb(boolean usb) {

        this.usb = usb;
    }

}

// B社製デスクトップ
class BDesktopPC extends DesktopPC implements TypeCommon {

    // 型名
    private String  typeName;
    // SDカード
    private boolean sd;

    // 型名を返す
    public String getTypeName() {

        return typeName;
    }

    // 型名を設定
    public void setTypeName(String typeName) {

        this.typeName = typeName;
    }

    // SDカードの利用状況を返す
    public boolean isSd() {

        return sd;
    }

    // SDカードの使用状況を設定
    public void setSd(boolean sd) {

        this.sd = sd;
    }
}

public class Sample10_3_1 {

    public static void main(String[] args) {

        ANotePC aPC = new ANotePC();
        BDesktopPC bPC = new BDesktopPC();

        // 型名を設定
        aPC.setTypeName("A-NPC1020");
        bPC.setTypeName("B-PC_typeD_ML");

        // 共通の型に各PCを設定
        TypeCommon[] typePC = { aPC, bPC };
        // 機種名を表示
        for (int i = 0; i < typePC.length; i++) {
            System.out.println("機種名は" + typePC[i].getTypeName() + "です。");
        }

    }
}
機種名はA-NPC1020です。
機種名はB-PC_typeD_MLです。

2時間目 インタフェースを学ぶに戻る     単位11 パッケージの導入に進む

単位10 抽象クラス及びインタフェースに戻る

トップページに戻る