Java8-两个接口包含具有相同方法签名但不同返回类型的默认方法,如何重写?

Java8-两个接口包含具有相同方法签名但不同返回类型的默认方法,如何重写?,java,interface,java-8,overriding,default-method,Java,Interface,Java 8,Overriding,Default Method,我理解,如果一个类实现了多个包含相同名称的默认方法的接口,那么我们需要在子类中重写该方法,以便显式定义我的方法将执行的操作。问题是,请参阅以下代码: interface A { default void print() { System.out.println(" In interface A "); } } interface B { default String print() { return "In interface B";

我理解,如果一个类实现了多个包含相同名称的默认方法的接口,那么我们需要在子类中重写该方法,以便显式定义我的方法将执行的操作。
问题是,请参阅以下代码:

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的print方法,即返回字符串并保持A的print不变的方法。但这段代码不会编译,因为:

Overrides A.print
The return type is incompatible with A.print()
很明显,编译器试图重写A的print方法,我不知道为什么

这是不可能的

:

如果返回类型为R1的方法声明
d1
覆盖或隐藏另一个返回类型为R2的方法声明
d2
,则
d1
必须是可替换为d2的返回类型,否则会发生编译时错误

:

返回类型为R1的方法声明
d1
,如果满足以下任一条件,则返回类型可替换为返回类型为R2的另一方法
d2

  • 如果
    R1
    void
    R2
    void

  • 如果
    R1
    是基本类型,则
    R2
    R1
    相同

  • 如果
    R1
    是参考类型,则以下情况之一为真:

    • R1
      ,适用于
      d2
      的类型参数,是
      R2
      的一个子类型

    • R1
      可以通过未选中的转换转换转换为
      R2
      的子类型

    • d1
      d2
      R1=| R2
      没有相同的签名

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

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

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

疯狂的想法:改变“工具”的顺序list@flowtron我的第一个直觉也是一样,不起作用。也许一个实现了a并将其print定义为final的类可以让你达到目的。。另一个疯狂的想法。@flowtron当然有其他的解决方法,但我想知道为什么这个功能是这样设计的。我主要关心的是覆盖接口B的“print()”方法,您提到的链接非常清楚地表明:
如果C类继承了一个具体方法,其签名与C继承的另一个方法的重写等效,则这是一个编译时错误。
因此我理解“发生了什么”,但“为什么”仍然不清楚!为什么编译器不能通过方法的签名识别我正在重写接口B的print()方法。或者你能告诉我为什么这是一种不好的做法吗?@Radiodef:这可能是类文件格式。所以,是的,没有技术上的原因。@RamanVerma:因为Java甚至不允许类
C
同时实现
A
B
,所以它是否能够识别覆盖的方法是无关紧要的。原因是它无法识别您在说
someInstanceOfC.print()
时调用的方法,至少在某种程度上不能不更改语言规则,Java设计者不希望这样做。@Eugene:在我看来,它与原始Java语言的所有其他设计决策保持一致,以使其简单且不易出错。即使在当前存在目标类型的版本中,根据预期的返回类型在不同的方法中进行选择也不是一个好主意。只需再添加一个方面:根据返回类型选择方法肯定不适合协变返回类型。继承一个返回
Number
的方法和另一个返回
Integer
的方法会产生相当模糊的问题。如果您覆盖了
整数
-返回方法,那么它会自动覆盖
数字
-返回方法吗,还是会以两种方法结束?我很高兴这种混乱局面没有得到支持。