繁体   English   中英

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

[英]Implementing two interfaces with two default methods of the same signature in 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());
    }
}

这是一个编译时错误。 你不能有来自两个接口的两个实现。

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

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());
    }
}

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

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

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

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

如果一个类实现了 2 个接口,这两个接口都有一个具有相同签名的 java-8 默认方法(如您的示例中所示),则实现类必须覆盖该方法 该类仍然可以使用I1.super.getGreeting();访问默认方法I1.super.getGreeting(); . 它可以访问其中之一,两者都可以访问,也可以都不访问。 所以以下将是 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();
    }


}

有一种情况,根据解析规则,这实际上是有效的。 如果接口之一扩展了其他接口之一。

使用上面的例子:

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

结果将是:

下午好!

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

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

然而,这有可能自我挫败。 如果一个类实现了两个从层次结构视图中不相关的接口,但都定义了相同的默认方法签名,那么扩展这两个接口的类将不会编译。 (如上所示)

可以想象,两个不同的库开发人员可以决定在不同时间使用公共签名添加默认方法; 事实上,这很可能会发生在实现类似概念的库中,例如数学库。 如果您碰巧在同一个类中实现了两个接口,那么您将在更新时崩溃。

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

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

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(); 
}  }

这是简单的方法:

public interface Circle{
 default String shape() {
    return "Circle drawn...";
 }
}

public interface Rectangle{
default String shape() {
    return "Rectangle drawn...";
}
}

public class Main implements Circle, Rectangle{       
@Override
public String shape() {
    return Circle.super.shape();// called using InterfaceName.super.methodName
}
}

Output:

画的圆...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM