web-dev-qa-db-ja.com

インターフェイスで定義されたメソッドの「デフォルト」実装とは何ですか?

コレクションインターフェイスで、その実装を含むremoveIf()という名前のメソッドを見つけました。

default boolean removeIf(Predicate<? super E> filter) {
    Objects.requireNonNull(filter);  
    boolean removed = false;  
    final Iterator<E> each = iterator();   
    while (each.hasNext()) {  
        if (filter.test(each.next())) {  
            each.remove();  
            removed = true;  
        }  
    }  
    return removed;  
}  

インターフェイスでメソッド本体を定義する方法があるかどうか知りたいですか?
defaultキーワードとは何ですか。どのように機能しますか?

90
gifpif

から https://dzone.com/articles/interface-default-methods-Java

Java 8は、「デフォルトメソッド」または(Defenderメソッド)新機能を導入します。これにより、開発者はこれらのインターフェイスの既存の実装を壊すことなく、インターフェイスに新しいメソッドを追加できます。具体的なクラスがそのメソッドの実装を提供できない場合にデフォルトとして使用するインターフェイス定義実装を許可する柔軟性を提供します。

public interface A {
    default void foo(){
       System.out.println("Calling A.foo()");
    }
}

public class ClassAB implements A {
}

新しい機能について初めて聞いたときにデフォルトの方法について尋ねられる一般的な質問が1つあります。

クラスが2つのインターフェイスを実装し、これらのインターフェイスの両方が同じシグネチャでデフォルトのメソッドを定義している場合はどうなりますか?

この状況を説明する例:

public interface A {  
    default void foo(){  
        System.out.println("Calling A.foo()");  
    }  
}

public interface B {
    default void foo(){
        System.out.println("Calling B.foo()");
    }
}


public class ClassAB implements A, B {

}  

このコードは、次の結果でコンパイルに失敗します。

Java: class Clazz inherits unrelated defaults for foo() from types A and B

これを修正するには、Clazzで、競合するメソッドをオーバーライドして手動で解決する必要があります。

public class Clazz implements A, B {
    public void foo(){}
}

しかし、独自のメソッドを実装する代わりに、インターフェイスAからメソッドfoo()のデフォルトの実装を呼び出したい場合はどうでしょうか。

次のようにA#foo()を参照することができます。

public class Clazz implements A, B {
    public void foo(){
       A.super.foo();
    }
}
161
gifpif

これらのメソッドはデフォルトメソッドと呼ばれます。 デフォルトのメソッドまたはDefenderメソッド新しく追加された機能 in Javaのいずれかです_ 8。

これらは、具象クラスがそのメソッドの実装を提供しない場合に、デフォルトとして使用される実装をインターフェイスメソッドが提供できるようにするために使用されます。

そのため、デフォルトのメソッドを使用したインターフェースがある場合:

public interface Hello {
    default void sayHello() {
        System.out.println("Hello");
    }
}

次のクラスは完全に有効です。

public class HelloImpl implements Hello {

}

HelloImplのインスタンスを作成する場合:

Hello hello = new HelloImpl();
hello.sayHello();  // This will invoke the default method in interface

便利なリンク:

49
Rohit Jain

私は少し研究をしましたが、次のことがわかりました。お役に立てれば。

既存の問題

通常のインターフェイスメソッドは抽象として宣言され、インターフェイスを実装するクラスで定義する必要があります。これにより、宣言されたすべてのメソッドを実装する責任をクラス実装者に負わせます。さらに重要なことは、これは「公開」後にインターフェースを拡張することが不可能であることも意味します。そうしないと、すべての実装者は実装を適応させなければならず、ソースおよびバイナリの後方互換性が破壊されます。

Java 8で採用されたソリューション

これらの問題に対処するために、JDK 8の新機能の1つは、既存のインターフェイスをデフォルトのメソッドで拡張できることです。 デフォルトのメソッドは宣言されるだけでなく、インターフェースでも定義されます。

注意すべき重要なポイント

  1. 実装者は、クラスを実装する際にデフォルトのメソッドを実装しないことを選択できます。
  2. 通常の最終クラス以外のメソッドをサブクラスでオーバーライドできるように、実装者はデフォルトのメソッドをオーバーライドできます。
  3. 抽象クラスは、デフォルトメソッドを抽象として(再)宣言することもでき、サブクラスにメソッドの再実装を強制します(「再抽象化」と呼ばれることもあります)。
17
Aniket Thakur