9章 インターフェース
1.インターフェースとは
 ひし形クラスと長方形クラスの両方の特徴を継承した正方形クラスのようなものを多重継承という。しかし、Javaでは多重継承の概念は取り入れられていません。これを解決するためにインターフェースという機能をサポートしている。
 インターフェースとは、定数とメソッドの宣言だけを集めたものである。宣言だけで実際のメソッド本体などは実装しない。あるクラスを作ろうとした場合に、「インターフェースをインプリメントする」と、そのクラスはインターフェースで宣言したメソッドと変数を必ず実装しなければならなくなる。
 つまり、MyInterfaceというインタフェースを作り、その中で「func1」というメソッドを宣言したとする。そして、MyClassを作ろうとした場合にMyInterfaceをインプリメントした場合、MyClassの中にはかならずfunc1というメソッドを実装する必要がある。
 一般的に継承は継投を表し、インターフェースは機能を表す。しかし、具体的な機能を決めるものではなく、このような機能があることを明示するためのものである。したがって、インターフェースはJavaのポリモーフィズムを実現する1つの手段であるといえる。
 ここで、例を示す。犬クラスは哺乳類クラスのサブクラスである。犬にも秋田犬クラス、ゴールデンレトリバークラスやブルドッククラスなどがサブクラスとして存在するかもしれない。これらは動物の種類の系統でサブクラスを作ってきている。また犬には、盲導犬や麻薬捜査犬、救助犬といった分類もあるが、これらはそれぞれ、盲人を誘導する機能を有するとか麻薬を見つけるとか救助するといった機能を表す。つまり、犬の種類とは関係ない。したがって、これらの機能)(インタフェース)をインプリメントした犬クラスが盲導犬クラスというように定義できるのである。
 今の世の中では盲導象や盲導猫というのは存在しないが、もしかすると将来盲導猫というものができたとすれば、猫クラスのサブクラスで、盲導インターフェースをインプリメントして盲導猫クラスを作ることができる。  
  
2 インターフェースの宣言 
interface interfaceName{
    type name = value
    type name = value                                           // 変数
    type method( paramType name… );           // メソッド
}
   

interface Shape2D{
     // 面積を計算する
  double getArea( );
}

 上記のようなShepe2Dインターフェースをインプリメントしたクラスは、必ずgetAreaメソッドを実装しなければならない。下記にその使用例を示す。 
 // 図形クラス
abstract class Shape{
    abstract void Display( );
}

// 円クラス
class Circle extends Shape implements Shape2D{
    int x;
    int y;
    int r;

    Circle ( int x, int r ){
        this.x = x;
        this.x = y;
        this.x = r;

    }

    void Display( ){
         System.out.println("x=" + x + ", y=" + y + ", r=" + r);
    }

    // 面積を計算する
    public double getArea( ){
         return r*r*Math.PI ;    // Math.PI:円周率
    }
}

    // 長方形クラス
class Rect extends Shape implements Shape2D{
        int x1;
       int y1;
       int x2;
       int y2;

     Rect ( int x1, int y1, int y2 ){
               this.x1 = x1;
               this.y1 = y1;
               this.x2 = x2;
               this.y2 = y2;
       } 

       void Display( ){
              System.out.println("x1=" + x1 + ", y1=" + y1 + ", x2=" + y2 + ", y2=" + y2);
       }

       // 面積を計算する
       public double getArea( ){
            // Math.abs : 絶対値を求めるメソッド
              return Math.abs(x1-x2) * Math.abs(y1-y2);
       }
}

 Shapeクラスは図形クラスであり、図形というからには何らかの形で表示する必要がある。表示方法は円や三角形、長方形など図形によって異なる。そこで、Shapeクラスでは実装できずサブクラスで実装する必要があるため、abstractになっている。
 Shapeクラスのサブクラスとして、ここではCircleクラス(円クラス)とRectクラス(長方形クラス)を定義している。ここでは、そのクラスの機能として面積を計算するためのShape2Dインターフェースをインプリメントしている。
  
3 インターフェースの参照 
Test.java
public class Test{
      public static void main(String args[ ]){
         Shape2D array[ ] = new Shape2D[5];

          array[0] = new Circle(5,3,2);
          array[1] = new Rect(5,3,20,7);
          array[2] = new Circle(3,1,1);
          array[3] = new Rect(0,0,3,3);
          array[4] = new Circle(-5,2,2);
 
          double area = 0;    // 面積 
          area += array[0].getArea( );
          area += array[1].getArea( );
          area += array[2].getArea( );
          area += array[3].getArea( );
          area += array[4].getArea( );
  

          System.out.println("面積の合計="+area);
      }
}
  

C:\java>java Test
面積の合計=97.27433388230814

C:\java>

  
4 インターフェースと修飾子 
 クラスにはpublic,protected,privateといった修飾子がある。インターフェースにもこれらの修飾子を使うことが可能である。もちろん、インターフェースに含まれる変数やメソッドにも用いることも可能である。
public interface Shape2D{
     // 面積を計算する
   public double getArea( );
}
  
5 インターフェースの継承 
 クラスには継承という機能がある。インターフェースにも継承という機能がある。クラスは多重継承ができないが、インターフェースは多重継承をすることができる。その場合、extendsの後に継承したいインターフェースをカンマで区切って記述する。
public interface Interface extends Interface1,Interface2{
     // 面積を計算する
   public double method( );
}
  
6 インターフェースとinstaceof演算子
 クラスはinstanceof演算子で、インスタンスがそのクラスのインスタンスか否かを判定することができる。インターフェースも同様にインスタンスが指定されたインターフェースをインプリメントかどうかをinstanceof演算子を用いて調べることができる。
 下記の例は、面積の合計を求める先ほどのサンプルをinstanceof演算子を用いて、円の面積の合計と長方形の面積の合計をそれぞれ算出するように書き換えたものである。
Test.java

public class Test{
   public static void main(String args[ ]){
         Shape2D array[ ] = new Shape2D[5];

         array[0] = new Circle(5,3,2);
         array[1] = new Rect(5,3,20,7);
         array[2] = new Circle(3,1,1);
         array[3] = new Rect(0,0,3,3);
         array[4] = new Circle(-5,2,2);

         double areaCircle = 0;    // 円の面積
         double areaRect   = 0;    // 長方形の面積

    for( int i = 0 ; i < array.length ; i++ ){
              if( array[i] instanceof Circle )
                  areaCircle += array[i].getArea( );

              else
                  areaRect   += array[i].getArea( );
        
}

         System.out.println("円面積の合計="areaCircle);
         System.out.println("長方形面積の合計="areaRect);
         System.out.println("面積の合計="+ (areaCircle + areaRect));
     }
}

C:\java>java Test
円面積の合計=28.274333882308138
長方形面積の合計=69.0
面積の合計=97.27433388230814

C:\java>