在Java 8中使用两个具有相同签名的默认方法实现两个接口

时间:2014-03-27 11:15:30

标签: java interface java-8

假设我有两个接口:

public interface I1
{
    default String getGreeting() {
        return "Good Morning!";
    }
}

public interface I2
{
    default String getGreeting() {
        return "Good Afternoon!";
    }
}

如果我想实现它们,将使用什么实现?

public class C1 implements I1, I2
{
    public static void main(String[] args)
    {
        System.out.println(new C1().getGreeting());
    }
}

6 个答案:

答案 0 :(得分:55)

这是编译时错误。您不能从两个接口实现两个实现。

但是,如果您在getGreeting中实施C1方法,这是正确的:

public class C1 implements I1, I2 // this will compile, bacause we have overridden getGreeting()
{
    public static void main(String[] args)
    {
        System.out.println(new C1().getGreeting());
    }

    @Override public String getGreeting()
    {
        return "Good Evening!";
    }
}

我只是想补充一点,即使I1中的方法是抽象的,而I2中的默认方法,也无法实现它们。所以这也是一个编译时错误:

public interface I1
{
    String getGreeting();
}

public interface I2
{
    default String getGreeting() {
        return "Good afternoon!";
    }
}

public class C1 implements I1, I2 // won't compile
{
    public static void main(String[] args)
    {
        System.out.println(new C1().getGreeting());
    }
}

答案 1 :(得分:23)

这不是特定的问题。但是,我仍然认为它为上下文增加了一些价值。作为@ toni77的答案的补充,我想补充一下,可以从实现类调用默认方法,如下所示。在下面的代码中,来自getGreeting()的默认方法interface I1是从重写的方法调用的:

public interface I1 {
     default String getGreeting() {
        return "Good Morning!";
     }
}

public class C1 implements I1, I2 {       
    @override
    public String getGreeting() {
        return I1.super.getGreeting();
    }
}

答案 2 :(得分:9)

如果一个类实现了两个接口,这两个接口都具有相同签名的java-8默认方法(如示例所示),则实现类为obliged to override the method。使用I1.super.getGreeting();的课程can still access the default method。它既可以访问,也可以访问。所以以下是C1

的有效实现
public class C1 implements I1, I2{
    public static void main(String[] args)
    {
        System.out.println(new C1().getGreeting());
    }

    @Override //class is obliged to override this method
    public String getGreeting() {
        //can use both default methods
        return I1.super.getGreeting()+I2.super.getGreeting();
    }

    public String useOne() {
        //can use the default method within annother method
        return "One "+I1.super.getGreeting();
    }

    public String useTheOther() {
        //can use the default method within annother method
        return "Two "+I2.super.getGreeting();
    }


}

答案 3 :(得分:2)

有一种情况,这实际上根据解决规则。如果其中一个接口扩展了其中一个接口。

使用上面的例子:

public interface I2 extends I1 {
    default String getGreeting() {
        return "Good Afternoon!";
    }
}

结果将是:

下午好!

但是,我认为这将是一个大问题。默认接口的全部原因是允许库开发人员在不破坏实现者的情况下发展apis。

可以理解的是,他们不允许在没有继承结构的情况下通过扩展来编译方法,因为库开发人员可能会劫持行为。

然而,这有可能自我失败。如果一个类实现了两个与分层视图无关的接口,但两者都定义了相同的默认方法签名,那么扩展这两个接口的类将无法编译。 (如上所示)

可以想象,两个不同的库开发人员可以决定使用共同签名在不同时间添加默认方法;事实上,这可能发生在实现类似概念的库中,例如数学库。如果您恰好是在同一个类中实现两个接口的抱歉的灵魂,您将在更新时被打破。

答案 4 :(得分:0)

我认为规则是实现重复默认方法的类必须'覆盖实现..以下编译并运行良好...

public class DupeDefaultInterfaceMethods {

interface FirstAbility {
    public default boolean doSomething() {
        return true;
    }
}

interface SecondAbility {
    public default boolean doSomething() {
        return true;
    }
}

class Dupe implements FirstAbility, SecondAbility {
    @Override
    public boolean doSomething() {
        return false;
    }
}

public static void main(String[] args) {
    DupeDefaultInterfaceMethods ddif = new DupeDefaultInterfaceMethods();
    Dupe dupe = ddif.new Dupe();
    System.out.println(dupe.doSomething());

    }
}
> false

答案 5 :(得分:0)

Java 8中的默认方法可以看作是多重继承的形式(除了不能继承该属性之外)。

默认方法背后的主要动机是,如果在某个时候需要将方法添加到现有接口,则可以在不更改现有实现类的情况下添加方法。这样,该接口仍与旧版本兼容。这是一个很酷的功能。但是,我们应该记住使用默认方法的动机,并应保持接口和实现的分离。

interface First{ 
    // default method 
    default void show(){ 
         System.out.println("Default method implementation of First interface."); 
}  } 

interface Second{ 
   // Default method 
   default void show(){ 
        System.out.println("Default method implementation of Second interface."); 
}  } 

// Implementation class code 
public class Example implements First, Second{ 
    // Overriding default show method 
    public void show(){
       First.super.show();
       Second.super.show();
} 
    public static void main(String args[]){ 
       Example e = new Example(); 
       e.show(); 
}  }