4

我在网上阅读了为什么Java中不允许多重继承的原因,并给出了以下示例来说明它:

class A { 
   public void doSomething() { 
   } 
} 

class B { 
     public void doSomething() { 
     } 
} 

class C extends A,B { 

} 

public static void main(String args) { 
     C c = new C(); 
     c.doSoemthing();   // compiler doesnt know which doSeomthing to call.

上面的示例说明了我们所说的菱形问题,其中两个父类具有相同的方法名称。当子类试图检索它时,编译器会感到困惑。

我的问题是,界面将如何解决此类问题?

4

7 回答 7

2

让我们考虑以下代码

interface P { 
   public void doSomething();
} 

interface Q { 
     public void doSomething();
} 
class A { 
   public void doSomething() { 
   } 
} 

class B { 
     public void doSomething() { 
     } 
} 

class C implements P,Q { 
     public void doSomething(){
         // implementation
     }
}

class D extends A,B {   // suppose it is possible


}

现在要使用 C 的对象,您可以doSomething()在 C 类中实现。仅在 C 类中实现。

但是如果你可以创建一个 D 的对象并调用doSomething应该调用哪个方法呢?因为此方法在 A 和 B 中都实现了。

钻石问题

实际上真正的钻石问题是

class A { 
   public void doSomething() { 
   } 
} 

class B extends A{ 
     public void doSomething() { 
     } 
} 

class C extends A{ 
     public void doSomething() { 
     } 
} 


class D extends B,C {   // suppose it is possible
   // no implementation of doSomething.
}

在此处输入图像描述

因其呈菱形而得名钻石。如果您想执行以下操作,请在此处

D d = new D();
d.doSomething(); // which method should be called now????

来自维基百科这里是一个很好的实时示例

例如,在 GUI 软件开发的上下文中,类 Button 可以继承自类 Rectangle(用于外观)和 Clickable(用于功能/输入处理),类 Rectangle 和 Clickable 都继承自 Object 类。现在,如果为 Button 对象调用 equals 方法,而 Button 类中没有这样的方法,但在 Rectangle 和 Clickable 中都有重写的 equals 方法,最终应该调用哪个方法?

于 2013-05-29T15:39:07.130 回答
2

说java中通过接口实现多重继承是不公平的

只支持multiple interface inheritancejava,java不支持multiple inheritance

您应该看到在mixin 继承中,一个类专门设计为用作多重继承方案中的类之一。

http://csis.pace.edu/~bergin/patterns/multipleinheritance.html

于 2013-05-29T15:30:40.973 回答
1

接口没有实现方法doSomething(),所以不能调用接口方法。接口只是在实际(实现)类中实现哪些方法的签名。您将doSomething()在您的类C中实现,这将是您在调用B.doSomething()or时调用的方法A.doSomething()

在使用两种方法扩展两个类的情况下doSomething(),它们可能具有不同的实现,您将不知道调用了哪一个。看这个例子:

class A { 
   public void doSomething() { 
       System.out.println("A");
   } 
} 

class B { 
   public void doSomething() { 
       System.out.println("B");
   } 
} 

class C extends A & B { //if this would be an option

} 

public static void main(String args) { 
    C c = new C(); 
    c.doSoemthing();   //Print "A" or "B" ???
}

结论:这是一个实现的东西。接口不为任何方法提供任何实现,因此从具有相同方法签名的接口继承是安全的。

于 2013-05-29T15:30:31.293 回答
0

多重继承可以继承许多类的成员数据以及它们的所有功能。多个接口只能继承函数原型,必须由子类实现

于 2013-05-29T15:28:42.800 回答
0

接口没有方法的实现,因此它们都将合并到同一个方法中。事实上,您的对象承诺实现一个名为 doSomething 的方法,但不绑定到特定的接口之一(同时提供两者)

于 2013-05-29T15:29:38.460 回答
0

这两个类都提供了 JVM 在调用时可以跳转到的代码。这就是歧义所在。与属性相同的问题,编译器可能有两个具有相同名称的属性要查看,这将产生类似的歧义。

接口不会提供该代码。因此不会有冲突。

支持多重继承的其他语言使编译器在出现这些歧义时禁止它们。并且需要临时解决这些问题。IE

class C{
    public void doSomething(){   
       // Call  (this inferred)
       B.doSomething();
       // leave A.doSomething() alone. 
    }
}
于 2013-05-29T15:29:53.940 回答
0

答案在于你的问题本身。如果接口编译器不会混淆,因为您的接口中没有实现。它是您的具体类,它将提供实际的实现。因此没有混淆。

于 2013-05-29T15:30:33.200 回答