多重继承是面向对象概念的一个特征,其中一个类可以继承多个父类的属性。当超类和子类中都存在具有相同签名的方法时,就会出现问题。在调用该方法时,编译器无法确定要调用哪个类方法,甚至在调用哪个类方法时也无法确定优先级。
注: Java不支持多重继承
例1:
JAVA
// Java Program to Illustrate Unsupportance of // Multiple Inheritance // Importing input output classes import java.io.*; // Class 1 // First Parent class class Parent1 { // Method inside first parent class void fun() { // Print statement if this method is called System.out.println( "Parent1" ); } } // Class 2 // Second Parent Class class Parent2 { // Method inside first parent class void fun() { // Print statement if this method is called System.out.println( "Parent2" ); } } // Class 3 // Trying to be child of both the classes class Test extends Parent1, Parent2 { // Main driver method public static void main(String args[]) { // Creating object of class in main() method Test t = new Test(); // Trying to call above functions of class where // Error is thrown as this class is inheriting // multiple classes t.fun(); } } |
输出: 编译错误被抛出
结论: 正如上面代码所描述的,使用测试对象调用fun()方法会导致复杂的问题,比如是调用Parent1的fun()还是Parent2的fun()方法。
例2:
GrandParent / / Parent1 Parent2 / / Test
代码如下
JAVA
// Java Program to Illustrate Unsupportance of // Multiple Inheritance // Diamond Problem Similar Scenario // Importing input output classes import java.io.*; // Class 1 // A Grand parent class in diamond class GrandParent { void fun() { // Print statement to be executed when this method is called System.out.println( "Grandparent" ); } } // Class 2 // First Parent class class Parent1 extends GrandParent { void fun() { // Print statement to be executed when this method is called System.out.println( "Parent1" ); } } // Class 3 // Second Parent Class class Parent2 extends GrandParent { void fun() { // Print statement to be executed when this method is called System.out.println( "Parent2" ); } } // Class 4 // Inheriting from multiple classes class Test extends Parent1, Parent2 { // Main driver method public static void main(String args[]) { // Creating object of this class i main() method Test t = new Test(); // Now calling fun() method from its parent classes // which will throw compilation error t.fun(); } } |
输出:
同样,当Run()方法将编译器错误抛出时,当使用C++之类的其他语言时,多个继承会导致钻石问题。从代码中,我们可以看到:使用Test object调用fun()方法会导致一些复杂问题,比如是调用Parent1的fun()还是Child的fun()方法。因此,为了避免这种复杂性,Java不支持类的多继承。
Java使用类不支持多重继承,处理多重继承导致的复杂性非常复杂。它会在各种操作(如强制转换、构造函数链接等)中产生问题,最重要的原因是,我们实际上需要多个继承的场景非常少,所以为了保持简单明了,最好省略它。 以上问题如何处理 默认方法和接口 ? Java8支持默认方法,接口可以提供方法的默认实现。一个类可以实现两个或多个接口。如果两个实现的接口都包含具有相同方法签名的默认方法,那么实现类应该明确指定要使用的默认方法,或者应该重写默认方法。
例3:
JAVA
// Java program to demonstrate Multiple Inheritance // through default methods // Interface 1 interface PI1 { // Default method default void show() { // Print statement if method is called // from interface 1 System.out.println( "Default PI1" ); } } // Interface 2 interface PI2 { // Default method default void show() { // Print statement if method is called // from interface 2 System.out.println( "Default PI2" ); } } // Main class // Implementation class code class TestClass implements PI1, PI2 { // Overriding default show method public void show() { // Using super keyword to call the show // method of PI1 interface PI1. super .show(); // Using super keyword to call the show // method of PI2 interface PI2. super .show(); } // Mai driver method public static void main(String args[]) { // Creating object of this class in main() method TestClass d = new TestClass(); d.show(); } } |
Default PI1Default PI2
注: 如果我们移除 实现了“TestClass”中的默认方法,我们得到了一个编译器错误。如果接口之间有菱形连接,那么中间接口都不提供根接口的实现就没有问题。如果它们提供了实现,那么可以使用super关键字如上所述访问实现。
例4:
JAVA
// Java program to demonstrate How Diamond Problem // Is Handled in case of Default Methods // Interface 1 interface GPI { // Default method default void show() { // Print statement System.out.println( "Default GPI" ); } } // Interface 2 // Extending the above interface interface PI1 extends GPI { } // Interface 3 // Extending the above interface interface PI2 extends GPI { } // Main class // Implementation class code class TestClass implements PI1, PI2 { // Main driver method public static void main(String args[]) { // Creating object of this class // in main() method TestClass d = new TestClass(); // Now calling the function defined in interface 1 // from whom Interface 2and 3 are deriving d.show(); } } |
Default GPI