Java 8 - 两个接口包含具有相同方法签名但不同 return 类型的默认方法,如何覆盖?

Java 8 -Two interfaces contain default methods with the same method signature but different return types, how to override?

我知道如果 class 实现了多个包含同名默认方法的接口,那么我们需要在子 class 中覆盖该方法,以便明确定义我的方法将做什么.
问题是,请看下面的代码:

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

interface B {
    default String print() {
        return "In interface B";
    }
}

public class C implements A, B {

    @Override
    public String print() {
        return "In class C";
    }

    public static void main(String arg[]) {
        // Other funny things
    }
}

现在接口 A 和 B 都有一个名为 'print' 的默认方法,但我想覆盖接口 B 的打印方法 - returns 一个字符串并保留 A 的打印原样.但是这段代码无法编译给出:

Overrides A.print
The return type is incompatible with A.print()

很明显,编译器正试图覆盖 A 的打印方法,我不知道为什么!

这是不可能的。

8.4.8.3:

If a method declaration d<sub>1</sub> with return type R<sub>1</sub> overrides or hides the declaration of another method d<sub>2</sub> with return type R<sub>2</sub>, then d<sub>1</sub> must be return-type-substitutable for d<sub>2</sub>, or a compile-time error occurs.

8.4.5:

A method declaration d<sub>1</sub> with return type R<sub>1</sub> is return-type-substitutable for another method d<sub>2</sub> with return type R<sub>2</sub> iff any of the following is true:

  • If R<sub>1</sub> is void then R<sub>2</sub> is void.

  • If R<sub>1</sub> is a primitive type then R<sub>2</sub> is identical to R<sub>1</sub>.

  • If R<sub>1</sub> is a reference type then one of the following is true:

    • R<sub>1</sub>, adapted to the type parameters of d<sub>2</sub>, is a subtype of R<sub>2</sub>.

    • R<sub>1</sub> can be converted to a subtype of R<sub>2</sub> by unchecked conversion.

    • d<sub>1</sub> does not have the same signature as d<sub>2</sub>, and R<sub>1</sub> = |R<sub>2</sub>|.

换句话说,void,返回原始和引用的方法只能重写和被相同类别的方法重写。 void 方法只能覆盖另一个 void 方法,返回引用的方法只能覆盖另一个返回引用的方法,依此类推。

您遇到的问题的一个可能解决方案是使用组合而不是继承:

class C {
    private A a = ...;
    private B b = ...;
    public A getA() { return a; }
    public B getB() { return b; }
}