关于继承:在Java中显式调用默认方法

Explicitly calling a default method in Java

Java 8引入了默认方法来提供扩展接口的能力,而不需要修改现有的实现。

我想知道,当某个方法被重写或由于不同接口中的默认实现冲突而不可用时,是否可以显式调用该方法的默认实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
interface A {
    default void foo() {
        System.out.println("A.foo");
    }
}

class B implements A {
    @Override
    public void foo() {
        System.out.println("B.foo");
    }
    public void afoo() {
        // how to invoke A.foo() here?
    }
}

考虑到上面的代码,您如何从类B的方法调用A.foo()


根据本文,您可以使用

1
A.super.foo();

这可以如下使用(假设接口AC都有默认方法foo())

1
2
3
4
5
6
7
8
9
10
11
12
13
public class ChildClass implements A, C {
    @Override    
    public void foo() {
       //you could completely override the default implementations
       doSomethingElse();
       //or manage conflicts between the same method foo() in both A and C
       A.super.foo();
    }
    public void bah() {
       A.super.foo(); //original foo() from A accessed
       C.super.foo(); //original foo() from C accessed
    }
}

AC都可以有.foo()方法,并且可以选择特定的默认实现,也可以使用其中一个(或两个)作为新foo()方法的一部分。还可以使用相同的语法访问实现类中其他方法中的默认版本。

方法调用语法的正式描述可以在JLS的第15章中找到。


下面的代码应该有效。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class B implements A {
    @Override
    public void foo() {
        System.out.println("B.foo");
    }

    void aFoo() {
        A.super.foo();
    }

    public static void main(String[] args) {
        B b = new B();
        b.foo();
        b.aFoo();
    }
}

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

输出:

1
2
B.foo
A.foo


此答案主要针对问题45047550(已关闭)中的用户。

Java 8接口介绍了多继承的一些方面。默认方法有一个已实现的函数体。要从超级类中调用方法,可以使用关键字super,但如果要使用超级接口进行调用,则需要显式命名。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class ParentClass {
    public void hello() {
        System.out.println("Hello ParentClass!");
    }
}

interface InterfaceFoo {
    default public void hello() {
        System.out.println("Hello InterfaceFoo!");
    }
}

interface InterfaceBar {
    default public void hello() {
        System.out.println("Hello InterfaceBar!");
    }
}

public class Example extends ParentClass implements InterfaceFoo, InterfaceBar {
    public void hello() {
        super.hello(); // (note: ParentClass.super is wrong!)
        InterfaceFoo.super.hello();
        InterfaceBar.super.hello();
    }

    public static void main(String[] args) {
        new Example().hello();
    }
}

输出:

Hello ParentClass!
Hello InterfaceFoo!
Hello InterfaceBar!


您不需要重写接口的默认方法。就这样称呼它:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class B implements A {

    @Override
    public void foo() {
        System.out.println("B.foo");
    }

    public void afoo() {
        A.super.foo();
    }

    public static void main(String[] args) {
       B b=new B();
       b.afoo();
    }
}

输出:

A.foo