実際の場面では,単一のクラスの性質だけではなく複数のクラスの性質を受け 継いだクラスを作りたいというケースが出てくることがある.このような要求に 対してダイレクトに答える方法は,複数のクラスを親クラスとするクラスを定義 することを可能にする方法である.これを多重継承(multiple inheritance)と呼 ぶ.
多重継承は自然ではあるが,継承しようとする複数のクラスで同じ名前のメソッ ドが定義されているときに,どの定義に従うかなどの曖昧さが生ずることがあ り,混乱しやすいという問題点がある.Java言語では,多重継承は採用せずに代 わりにインタフェースという仕組みを用意している.
インタフェースはそのインタフェース自体のインスタンスを持たない点で,抽象 クラスと良く似ている.しかし,抽象クラスと違って,メソッドの引数の型,返 り値の型を定義するだけで,中身(実装)は定義できない(abstractメソッドと似ている).インタフェースの定義の例を見てみる.
interface I { public void hello(String s); public void bye(String s); }クラスの継承では「親クラスを継承してサブクラスを作る」と言うが,インタフェースの場合は,「インタフェースを実装(implement)したクラスを作る」と言う.インタフェースIを実装したクラスBの定義の例を見てみる.
class B implements I{ B(){} public void hello(String s){ System.out.println("Hello "+s+" in B"); } public void bye(String s){ System.out.println("bye "+s+" in B"); } }あるインタフェースを実装する場合は,そのインタフェースで定義されている すべてのメソッドを定義する必要があるので注意が必要である.
あるクラスは複数のインタフェースを実装することが可能である.インタフェースIとインタフェースJを実装するクラスを定義するときは,
class B implements I,J { ... }のように書く.
あるクラスCのサブクラスであり,かつインタフェースIを実装しているクラスD の定義は以下のようにおこなう.
// クラスCのサブクラスでインタフェースIを実装しているクラスDの定義 class D extends C implements I{ // Dのコンストラクタの宣言 D(int v){ // 親クラスCでコントラクタ「C(int v)」が定義されているとしてその呼び出し super(v); } // インタフェースIで宣言されているhelloの実装 public void hello(String s){ System.out.println("Hello "+s+" in D("+val+")"); } public void bye(String s){ System.out.println("Bye "+s+" in D("+val+")"); } }これらをまとめて,テストするプログラム全体は以下のようになる.
interface I{ public void bye(String s); public void hello(String s); } class B implements I, J{ B(){} public void hello(String s){ System.out.println("Hello "+s+" in B"); } public void bye(String s){ System.out.println("bye "+s+" in B"); } } class C{ int val; C(int v){ val=v; } int add(int x){ val+=x; return val; } } class D extends C implements I{ D(int v){ super(v); } public void hello(String s){ System.out.println("Hello "+s+" in D("+val+")"); } public void bye(String s){ System.out.println("Bye "+s+" in D("+val+")"); } } class t{ static void callHello(I i,String s){ i.hello(s); } static void callBye(I i,String s){ i.bye(s); } public static void main(String[] args){ B b=new B(); callHello(b,"B"); D d=new D(3); callHello(d,args[0]); d.add(4); callHello(d,args[0]); callBye(b,args[0]); callBye(d,args[0]); } }この実行例は以下のようになる.
Macintosh-5:/tmp ktanaka$ java t "tanaka" Hello B in B Hello tanaka in D(3) Hello tanaka in D(7)
インタフェースに関しては,サブインタフェース,インタフェース変数など, さらに細かい話題もあるが,システムで用意されたインタ フェースを実装するクラスを作ることはあるものの,自分でインタフェースを 定義することはあまりないと思われるので,詳しい説明はおこなわない.