AVA-8:インターフェース


8コネクタ


8.1インタフェースの定義



インタフェースは,オブジェクトと外部の相互作用を抽象化していると見なすことができる.すなわち,インタフェースは基本的に定数と抽象メソッドの集合であり,実装クラスは実装動作によってインタラクションを定義する.
interface  TV {
    public void powerOn();
    public void powerOff();
}
このとき,各メソッドは抽象メソッドであるが,インタフェースではpublicのみを宣言することもpublic abstract finalと見なす.

8.2インタフェースの実施


8.2.1基本実施


特定のインタフェースを実現するためには,動作を定義するクラスが必要である.次にimplementsキーワードで実装するインタフェースを指定すればよい.
public class RemoteController implements TV {
    @Override
    public void powerOn(){
        System.out.println("Power ON");
    }
    @Override
    public void powerOff(){
        System.out.println("Power OFF");
    }
    
    public void click(){
        System.out.println("Button Clicked");
    }
}
上記の例に示すように、インタフェースを実装するためには、インタフェースが有するすべての抽象的な方法を上書きする必要がある.

8.2.2匿名の実施対象


匿名実装オブジェクトとは、ファイルの管理を必要とせずにインタフェースを一度に実装するオブジェクトです.すなわち、インプリメンテーションオブジェクトは、ソースファイルを必要とせずに作成されます.基本的な使い方は以下の通りです.
인터페이스 변수 = new 인터페이스(){
    // 추상 메서드들 모두 구현
};
注意事項はオブジェクトを作成するため、最後にセミコロン(;)彼にやるべきだ.主にJava 8におけるラムダ式またはUIプログラミングにおけるイベント処理に用いられる.

8.2.3インタフェースリファレンス


インタフェースは、オブジェクトと外部のインタラクションを抽象化し、任意のインプリメンテーションクラスが外部で操作できることを意味し、インタフェースリファレンス(参照変数)は、異なる独自のクラスをインプリメンテーションする任意のクラスを参照することができる.例は、一般的なコレクションフレームワークのリストを示します.
import java.util.List; 
import java.util.ArrayList;
import java.util.LinkedList;

public class Main{
    public static void main(String args[]){
        // list as an ArrayList
        List<Integer> list = new ArrayList<Integer>();
        // list as a LinkedList
        list = new LinkedList<Integer>();
    }
}
以上のように、Listインタフェースを実現するArrayListおよびLinkedListタイプのオブジェクトは、Listタイプとして報告され、List Referenceはそれらを指すことができる.ただし,実装インタフェースのクラスをReferenceと書かずにインタフェースをReferenceと書く場合,実装クラスが持つ固有の手法はインタフェースReferenceでは使用できない点に注意が必要である.

8.3インタフェースの継承


まず、Javaでよく言われる継承はクラス間の継承についてです.クラス間の継承は基本的にマルチレベル継承であってもよいが、マルチレベル継承ではない.ただし、インタフェースはインタフェース間の多重継承をサポートします.

ただし,すべての場合に多重継承が可能であるわけではない.メソッドシンボルは同じですが、戻りタイプが異なるとコンパイルエラーが発生します.
しかし、なぜクラスはマルチ継承をサポートしないのに、インタフェースはマルチ継承をサポートしているのでしょうか.

8.3.1ダイヤモンド問題



複数の継承は、1つのクラスが複数の親を継承する過程で上記の関係を確立します.祖先クラスで定義されたFunc()のメソッドがあり、各親クラスが必要に応じて再定義されます.これは、どのFunc()操作を実行すべきか分からないため、サブクラスが競合します.
しかし,インタフェースは抽象メソッドの集合である.つまり、多重継承の条件に違反しないと、エンティティのないメソッドであるため、競合は発生しません.

8.4インタフェース変更点


8.4.1 Java 8,デフォルトメソッド


Java 8に追加されたDefaultメソッドは、既存の抽象メソッドセットの概念とは逆です.次の例です.
interface  TV {
    public void powerOn();
    public void powerOff();
    default void soundUp(){
    	System.out.println("Sound Up");
    }
}
テレビインタフェースではdefaultメソッドsoundUpが実装部分的に存在することに注目すべきである.では、java 8にこれらの機能を追加する理由について説明します.
インタフェースには、インタフェースを実装するクラスで、単独で実装することなく使用できる実装部分があります.では、当初は抽象的なクラスにすればいいのではないかと考えられます.しかし、このデフォルトメソッドを使用する良いタイミングは、インタフェースを初めて定義するときではありません.
実装済みインタフェースの実装クラスに新しい機能を追加すべきであることを考えてみましょう.従来の方法であれば、メソッドを宣言し、各インプリメンテーションクラスで動作を1つずつ実装する必要があります.ただし、基本的な方法では、既存のインタフェースを変更するだけで、すべてのインプリメンテーションクラスでこの機能を使用できます.また、必要に応じてインプリメンテーションクラスで再定義することもできます.
この利点は,開発作業効率の面に加えて,システム安定性の面でも利点がある.デフォルトのメソッドは、このインタフェースを実装するすべてのクラスにも適用されます.すなわち,実装クラスは修正後の新しいインタフェースと競合する心配はない.
ただし、default methodを使用する場合は注意が必要です.インタフェースの多重継承におけるダイヤモンド問題である.

8.4.2 Java 8、静的方法

static 리턴타입 메소드명 (매개변수) {
    // 기능
}
Static Methodはdefaultメソッドと同様に,実装制限を受けずに定義できるが外部から再定義できないメソッドである.また、インタフェースインスタンス(インプリメンテーションオブジェクト)を必要とせずにメソッドを呼び出す利点があります.
interface Calculator {
    static int sum(int a, int b) {
        return a+b;
    }    
}
public class Main{
    public static void main(String args[]){
        int result = Calculator.sum(1,2);
    }
}
他のメソッドからstaticメソッドを呼び出す場合、同じstaticしか使用できないことに注意してください.

8.4.1 Java 9、プライベートメソッド


JAva 9にはprivateメソッドとprivate staticメソッドが追加されています.これまでの方法は基本的に外部からのアクセスを許可する方法であった.すなわち,インタフェースに登録する方法は外部に知られていない方法(パッケージ)はない.そのため,プライベートアクセス制御者が増加し,これを利用してインタフェース内部でのみ動作を実行できるようになった.
interface Calculator {
    public void powerOn();
    
    default int result(a,b){
        return add(a,b);
    }
    
    private int add(int a, int b){
        return a + b;
    }
}
   
privateメソッドにも実装部があることがわかる.ただし、以前であれば2つのdefaultメソッドを使用していたが、privateメソッドの追加に伴い外部ではadd()の存在は分からないが、内部ではaddの機能を使用している.