実際の場面では,単一のクラスの性質だけではなく複数のクラスの性質を受け 継いだクラスを作りたいというケースが出てくることがある.このような要求に 対してダイレクトに答える方法は,複数のクラスを親クラスとするクラスを定義 することを可能にする方法である.これを多重継承(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)
インタフェースに関しては,サブインタフェース,インタフェース変数など, さらに細かい話題もあるが,システムで用意されたインタ フェースを実装するクラスを作ることはあるものの,自分でインタフェースを 定義することはあまりないと思われるので,詳しい説明はおこなわない.