如何使用 Java 中的默认方法解决菱形问题?

继承 是两个类之间的关系,其中一个类继承另一个类的属性。这种关系可以使用 extends 关键字定义为 -

public class A extends B{
}

继承属性的类称为子类或子类,继承属性的类称为超类或父类。

在继承中,在子类对象中创建了超类成员的副本。因此,使用子类对象可以访问这两个类的成员。

多重继承:

有多种类型的继承可用,即单级、多级、分层、多级和混合。

在多重继承中,一个类继承了多个类的属性。换句话说,在多重继承中,我们可以有一个子类和 n 个父类。Java 不支持多重继承(使用类)。

钻石问题

例如,让我们假设 Java 确实支持多重继承。有了这个假设,考虑下面的例子。

示例

在这里,我们有一个名为Sample的抽象类,其抽象方法为 -

public class abstract Sample {
   public abstract demo();
}

然后在同一个包/文件夹中,我们有两个类扩展这个类并尝试实现它的抽象方法,demo().

public class Super1 extends Sample{
   public void demo() {
      System.out.println("demo method of super1");
   }  
}
public class Super2 extends Sample{
   public void demo() {
      System.out.println("demo method of super2");
   }  
}

根据我们的假设,由于 Java 支持多重继承,我们试图继承 Super1 和 Super2 两个类。

public class SubClass extends Super1, Super2 {  
   public static void main(String args[]) {
      SubClass obj = new SubClass();
      obj.demo();
   }
}

然后,根据继承的基本规则,demo()应在子类对象中创建两个方法的副本,从而使子类具有两个具有相同原型(名称和参数)的方法。那么,如果demo()使用子类的对象调用方法,编译器就会面临不知道调用哪个方法的模棱两可的情况。这个问题在 Java 中被称为钻石问题。

由于此Java 不支持多重继承,即,您不能扩展多个其他类。不过,如果您尝试这样做,则会生成编译时错误。

编译时错误

在编译时,上述程序会产生以下错误 -

MultipleInheritanceExample.java:9: error: '{' expected
public class MultipleInheritanceExample extends MyInterface1, MyInterface2{
                                                            ^
1 error

解决方案

您可以使用默认方法 (Java8) 和接口在 Java 中实现多重继承。

从 Java8 开始,接口中引入了默认方法。与其他抽象方法不同,这些是具有默认实现的接口的方法。如果您在接口中有默认方法,则不必在已经实现此接口的类中覆盖(提供主体)它。

您可以在两个不同的接口中拥有相同的默认方法(相同的名称和签名),并且您可以从一个类中实现这两个接口。

如果这样做,则必须覆盖类中的默认方法,显式指定默认方法及其接口名称。

示例

interface MyInterface1{  
   public static int num = 100;
   public default void display() {
      System.out.println("display method of MyInterface1");
   }
}
interface MyInterface2{  
   public static int num = 1000;
   public default void display() {
      System.out.println("display method of MyInterface2");
   }
}  
public class InterfaceExample implements MyInterface1, MyInterface2{
   public void display() {
      MyInterface1.super.display();
      //or,
      MyInterface2.super.display();
   }      
   public static void main(String args[]) {
      InterfaceExample obj = new InterfaceExample();
      obj.display();
   }
}
输出结果
display method of MyInterface1
display method of MyInterface2