Java言語入門 〜C言語を学んだ君へ〜
[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 {
:
}