12

Java 8では、次のようなものがあります:

package test;
public class SimpleFuncInterfaceTest {
    public static void carryOutWork(AFunctionalInterface sfi){
        sfi.doWork();
    }
    public static void main(String[] args) {
        carryOutWork(() -> System.out.println("Do work in lambda exp impl..."));
        AImplementor implementsA = new AImplementor();
        //carryOutWork(() -> implementsA.doWork());
        BImplementor implementsB = new BImplementor();
        carryOutWork(() -> implementsB.doWork());
    }
}

@FunctionalInterface
interface AFunctionalInterface {
    public void doWork();
    default public void doSomeWork(){
        System.out.println("FOO");
    }
}

@FunctionalInterface
interface BFunctionalInterface extends AFunctionalInterface {
    @Override
    default public void doSomeWork(){
        System.out.println("BAR");//Unreachable in same object?
    }
}

class AImplementor implements AFunctionalInterface {
    @Override
    public void doWork() {
        doSomeWork();
    }
}

class BImplementor extends AImplementor implements BFunctionalInterface {
    public void doSomeWork(){
        super.doSomeWork();
        new BFunctionalInterface(){
            @Override
            public void doWork() {
            }}.doSomeWork();
            System.out.println("WUK WUK");
    }
    @Override
    public void doWork() {
        doSomeWork();
    }
}

匿名の内部クラスを作成してそれを呼び出すことなく、implementsB からデフォルトの機能インターフェイスの動作を呼び出す方法はありますか?

これには副作用があり (implementsA のメソッドを 2 回呼び出す)、必要な場合は親の実装への呼び出しが必要であり、必要に応じていくつかの特殊化と共に、子の実装で子の既定の実装を呼び出すことができます。ご覧のとおり、親の実装を呼び出すのは非常に簡単ですが、子インターフェイスを実装するクラスに間接レイヤーを追加しない限り、デフォルトの実装を書き直さないようにする方法がわかりません。また、それを強制する方法もありません。 .

たとえば、A がデータベースなどのリソースへのアクセスをロック解除または提供し、B が 2 番目のリソース (別のデータベース) のロックを解除した場合、コードで A をロック解除し、B が機能インターフェイスを使用してこのコントラクトを強制する方法がわかりません。 AとBが呼び出されます。 1 レベルの深さでは実行できますが、N レベルの深さでは不可能のようです。

私はラムダを使用して、コストのかかる呼び出しを回避し、ライブラリのユーザーに操作の意味的な順序を強制するつもりでした。

この質問は、「Java で既定のメソッドを明示的に呼び出す」とはまったく同じではありません。この質問は、親インターフェイスの既定のメソッドを呼び出すだけでなく、N レベルの深さのインターフェイスに関するものであるためです

4

1 に答える 1

26

interface defaultを使用して、継承されたメソッドを呼び出すことができますInterfaceName.super。ルールは他のメソッド呼び出しと同じsuperです。オーバーライドした継承メソッドを呼び出すことはできますが、継承メソッドがオーバーライドした可能性のあるメソッドを直接呼び出すことはできません。例えば

interface A
{
    void foo();
    default void toOverride() {
        System.out.println("A");
    }
}
interface B extends A
{
    default void toOverride() {
        A.super.toOverride();
        System.out.println("B");
    }
}
interface C extends B
{
    default void toOverride() {
        A.super.toOverride();// does not work
        B.super.toOverride();
        System.out.println("B");
    }
}
class D implements B
{
    public void toOverride() {

    }    
    public void foo() {
        D.this.toOverride();
        B.super.toOverride();
        A.super.toOverride(); // does not work!
    }
}

しかし、各オーバーライド メソッドがそのスーパー メソッドを呼び出す場合は、一連の呼び出しがあります。ただし、インターフェイスについて話していることに注意してください。実装はsuper、まったく呼び出すことなく、常にデフォルト メソッドをオーバーライドできます。

于 2014-06-18T08:15:07.647 に答える