ほぷしぃ

Java言語入門 〜C言語を学んだ君へ〜

[第10回] インタフェース

[1] インタフェースの基本

今まで継承をメインに進めてきましたが、継承だけではどうしても駄目な点がありました。
そう、多重継承(class A extends B, C等)ができない点です。
その多重継承を解決するために用意されているものが、これから説明するインタフェースなのです。
この継承に似ているインタフェースがどういうもので、どのような機能があるか、どんな時に使うのかを覚えてください。

インタフェースとは

まずは、インタフェースがどういうものなのか説明します。

インタフェースとは、「定数」と「抽象メソッド」をひとまとめにしたもの

定数とは文字通り、変更不可の値のことです。第9回で説明しました、finalのことです。
抽象メソッドとは、オーバーライドを前提に定義したメソッドです。abstractのことです。
では、このインタフェースをどのように使用するかを説明します。
まずは、次のクラス図を見てください。これは、誤った例です。
誤ったクラス図
「人間」から「警察官」を、「犬」から「警察犬」を継承しています。
一見良さそうですが、このような継承の仕方は誤りです。理由は、

継承とは「系統」を表す

ものだからです。上の図では哺乳類の種類を系統化したものであり、
「警察官」や「警察犬」は哺乳類の継承に当てはまらないからです。
生まれた時から「警察官」の人はいません。

では、どうすればよいでしょうか。ここで登場するのが、インタフェースです。
継承は「系統」に使用しますが、インタフェースは「機能」として使用します。
つまり、人間と犬に「警察」という「機能」を付ければよいのです。
誤ったクラス図
これで、正しい「警察官」と「警察犬」ができました。
もし、「医者」になりたければ医者のインタフェースを付けるだけです。
プログラムの世界は簡単に職業が選べます。
インタフェースの説明は以上です。
継承とインタフェースの違いはわかりにくいと思いますが、
以降で少しずつインタフェースの理解を深めてください。

インタフェースの基本形

インタフェースを定義するには、interfaceというキーワードを使います。
次のように記述します。

interface Name{
    int VALUE = 10; // 定数
    void method(); // 抽象メソッド
}

Nameにはインタフェース名を書きます。
そして、「定数」と「抽象メソッド」はいくつ記述してもかまいません。
また、不思議に思ったでしょうが「final」を使わなくても、「int VALUE = 10;」で定数になります。
さらに「abstract」を付けなくても「void method();」で抽象メソッドになります。

インタフェースには「定数」と「抽象メソッド」のキーワードを意識する必要はない

この部分はとても大切なので覚えましょう。
そして、「抽象メソッド」は「機能」として使われるため、外部公開が必要になります。
したがって、上記の定義方法は以下の定義方法と全く同じ意味になります。

interface Name{
    public static final int VALUE = 10; // 定数
    public abstract void method(); // 抽象メソッド
}

「定数」には「public static final」を、「定義」には「public abstract」を付けることがあらかじめ決まっています。
そのため、あえて書く必要はなく、省略ができます。

[2] インタフェースの実装

インタフェース内で定義した「抽象メソッド」に「中身を書く」ことを実装と言います。
では、実際に実装します。次のソースを見てください。

サンプルプログラム

// インタフェースA
interface InterA {
    int VALUE_A = 10;
    void methodA();
}
// インタフェースB
interface InterB {
    int VALUE_B = 20;
    void methodB();
}
// インタフェースを実装するクラス
class AB implements InterA, InterB {
    // 実装
    public void methodA() {
        System.out.println("methodAの実装");
    }

    // 実装
    public void methodB() {
        System.out.println("methodBの実装");
    }
}
public class Java10_01 {
    public static void main(String args[]) {
        // クラスABの定数を表示
        System.out.println(AB.VALUE_A);
        System.out.println(AB.VALUE_B);

        AB ab = new AB();
        // クラスABのメソッドの呼び出し
        ab.methodA();
        ab.methodB();
    }
}

実行結果

実行結果

今回はインタフェースを2つ定義しました。インタフェースAとインタフェースBです。
そして、クラスABでインタフェースを実装してします。

インタフェースを実装するときはimplementsキーワード

クラスの時は「extends」を使いましたが、インタフェースの場合には「implements」を使います。
このとき、実装するインタフェースはいくつでもかまいません。
継承と違って複数実装することができるわけです。複数の場合は「,」で区切ります。
その後、指定したインタフェースにある抽象メソッドを実装、つまり「オーバーライド」します。
実装しなければ、コンパイルエラーが起こります。
クラスJava10_01では、クラスABにある定数と、メソッドを呼び出しています。
実行結果より、クラスABで定義しなかった定数も使用できることが確認できます。

[3] インタフェースの継承

インタフェースにも継承があります。継承をするには「extends」を使います。
これはクラスの継承と同じです。しかし、クラスと違って、インタフェースでは「多重継承」ができます。
次のソースを見てください。

サンプルプログラム

// インタフェースA
interface InterA {
    int VALUE_A = 10;
    void methodA();
}
// インタフェースB
interface InterB {
    int VALUE_B = 20;
    void methodB();
}
// インタフェースC(2つのインタフェースを継承)
interface InterC extends InterA, InterB {
    int VALUE_C = 30;
    void methodC();
}

// インタフェースを実装するクラス
class AB implements InterC {
    // 実装
    public void methodA() {
        System.out.println("methodAの実装");
    }
    // 実装
    public void methodB() {
        System.out.println("methodBの実装");
    }
    // 実装
    public void methodC() {
        System.out.println("methodCの実装");
    }
}
public class Java10_02 {
    public static void main(String args[]) {
        // クラスABの定数を表示
        System.out.println(AB.VALUE_A);
        System.out.println(AB.VALUE_B);
        System.out.println(AB.VALUE_C);

        AB ab = new AB();
        // クラスABのメソッドの呼び出し
        ab.methodA();
        ab.methodB();
        ab.methodC();
    }
}

実行結果

実行結果

インタフェースInterCがInterAとInterBを「多重継承」しています。
この場合、継承するごとに「,」で区切ります。
「継承」によって、インタフェースInterCは、3つのインタフェースの機能を持つことになります。
そのため、クラスABはインタフェースInterCのみを指定するだけで、
3つのインタフェースの機能を使えるようになります。

Javaはクラスの「多重継承」をサポートしていません。
その理由は複数のクラスの変数やメソッドを継承すると、機能が複雑になってしまうからです。
しかし、インタフェースは「定数」と「抽象メソッド」しか定義していません。
そのため、いくつ継承しても複雑にならず「多重継承」ができます。

[4] インタフェースのアクセス修飾子

インタフェースにもアクセス修飾を付けることができます。次のように書きます。
public interface InterA { : }



第9回へ ページのトップへ 次のページへ