Java接口如何模拟多重继承?

jac*_*nad 74 java interface multiple-inheritance

我正在阅读"The Java Tutorial"(第二次).我刚刚完成了关于接口的部分(再次),但仍然不了解Java接口如何模拟多重继承.是否有比书中更清楚的解释?

Pet*_*ans 151

假设您的域中有两种东西:卡车和厨房

卡车有一个driveTo()方法和Kitchens有一个cook()方法.

现在假设泡利决定从送货卡车后面出售比萨饼.他想要一个他可以驾驶To()和烹饪()的东西.

在C++中,他会使用多重继承来执行此操作.

在Java中被认为太危险,因此您可以从主类继承,但是您可以从接口"继承"行为,这些行为用于所有意图和目的,抽象类没有字段或方法实现.

所以在Java中,我们倾向于使用委托实现多重继承:

Pauli将一辆卡车子类化,并在一个名为kitchen的成员变量中为卡车添加了一个厨房.他通过调用kitchen.cook()实现了Kitchen接口.

class PizzaTruck extends Truck implements Kitchen {
   Kitchen kitchen;

   public void cook(Food foodItem) {
      kitchen.cook(foodItem);
   }
}
Run Code Online (Sandbox Code Playgroud)

他是一个快乐的人,因为他现在可以做的事情;

pizzaTruck.driveTo(beach);
pizzaTruck.cook(pizzaWithExtraAnchovies);
Run Code Online (Sandbox Code Playgroud)

好吧,这个愚蠢的故事是为了表明它不是多重继承的模拟,它是真正的多重继承,附带条件是你只能继承契约,只能从称为接口的空抽象基类继承.

(更新:随着默认方法接口的出现,现在也可以提供一些继承的行为)

  • 谢谢.我发现这个愚蠢的故事最有帮助. (22认同)
  • 如果Truck和Kitchen都是带有字段的类,我们需要PizzaTruck中的所有字段,该怎么办?例如,实现PizzaTruck.shootPizzasBackwards(),减少PizzaCount(A Kitchen字段)并提高速度(A Truck字段) (10认同)
  • 如果Kitchen不是一个界面而是另一个类怎么办? (7认同)
  • @bizmark:然后创建一个接口Cookery(带有`public void cook()`),Kitchen和PizzaTruck都会实现. (2认同)

Mic*_*rdt 18

您可能会感到困惑,因为您在本地查看多个继承,就一个类继承多个父项的实现详细信息而言.这在Java中是不可能的(并且经常导致在可能的语言中滥用).

接口允许多种类型的继承,例如a class Waterfowl extends Bird implements Swimmer可以被其他类使用,就好像它是a Bird ,就好像它是a Swimmer.这是多重继承的深层含义:允许一个对象一次性地属于几个不相关的不同类.


Rea*_*als 16

这是一种通过java中的接口实现多重继承的方法.

要做什么?
A类扩展B,C //这在java中是不可能的,但可以间接实现.

class B{
   public void getValueB(){}
}

class C{
   public void getValueC(){}
}


interface cInterface{
   public getValueC();
}

class cChild extends C implemets cInterface{
    public getValueC(){

      // implementation goes here, call the super class's getValueC();

    }
}


// Below code is **like** class A extends B, C 
class A extends B implements cInterface{
   cInterface child =  new cChild();
   child.getValueC();
}
Run Code Online (Sandbox Code Playgroud)


dav*_*rld 10

鉴于以下两个接口......

interface I1 {
  abstract void test(int i);
}
interface I2 {
  abstract void test(String s);
}
Run Code Online (Sandbox Code Playgroud)

我们可以使用下面的代码实现这两个...

public class MultInterfaces implements I1, I2 {
  public void test(int i) {
    System.out.println("In MultInterfaces.I1.test");
  }
  public void test(String s) {
    System.out.println("In MultInterfaces.I2.test");
  }
  public static void main(String[] a) {
    MultInterfaces t = new MultInterfaces();
    t.test(42);
    t.test("Hello");
  }
}
Run Code Online (Sandbox Code Playgroud)

我们不能扩展两个对象,但我们可以实现两个接口.


Boz*_*zho 10

接口不模拟多重继承.Java创建者认为多重继承是错误的,因此在Java中没有这样的东西.

如果要将两个类的功能合并为一个 - 使用对象组合.即

public class Main {
    private Component1 component1 = new Component1();    
    private Component2 component2 = new Component2();
}
Run Code Online (Sandbox Code Playgroud)

如果要公开某些方法,请定义它们并让它们将调用委托给相应的控制器.

这里的接口可能很方便 - 如果Component1实现接口Interface1Component2实现Interface2,您可以定义

class Main implements Interface1, Interface2
Run Code Online (Sandbox Code Playgroud)

这样您就可以在上下文允许的情况下交替使用对象.


Eri*_*pen 6

你知道吗,从一个JavaScript开发人员的角度来看,试图了解这些东西到底发生了什么,我想指出一些事情,有人请告诉我,如果我在这里,我在这里缺少什么离开标记的方式.

接口非常简单.愚蠢,非常简单.他们像人们最初想的那样愚蠢,非常简单,这就是为什么关于这个确切的主题存在如此多的重复问题,因为使用它们的一个原因已经被人们试图制造出比他们更多的人所不清楚了在我曾经接触到的每个Java服务器端代码库中都被广泛滥用.

那么,你为什么要使用它们呢?大多数时候你不会.你肯定不会像许多人想的那样一直使用它们.但在我到达之前,让我们谈谈他们不是什么.

接口不是:

  • 以任何方式解决Java缺乏的任何类型的继承机制.它们与继承无关,它们从未做过,也绝不模拟任何类似继承的东西.
  • 必要的东西可以帮助你写你写的东西,所以它可以帮助其他人写一些意味着你的东西接口的东西.

它们真的很简单,你认为它们一目了然.人们总是愚蠢地滥用,所以很难理解这一点.这只是验证/测试.一旦你写了一些符合接口的东西并且有效,删除那些"实现"代码就不会破坏任何东西.

但是,如果您正确使用接口,则不希望将其删除,因为在那里使用接口为下一个开发人员提供了一个工具,用于为另一组数据库或Web服务编写访问层,他们希望应用程序的其余部分继续使用是因为他们知道他们的类会失败,直到他们获得100%完全按预期的界面.所有接口都是验证您的类,并确定您实际上已实现了您承诺的接口.而已.

它们也是便携式的.通过公开您的接口定义,您可以为想要使用未暴露代码的人提供一组符合的方法,以便他们的对象能够正确使用它.他们不必实现接口.他们可以把它们放在一张记事本纸上并仔细检查.但是通过界面,您可以获得更多保证,除非有适当版本的接口,否则不会尝试工作.

那么,任何界面都不可能被多次实现?完全没用.多重继承?停止伸手去抓那条彩虹.Java首先避免使用它们,并且无论如何,合成/聚合对象在很多方面都更加灵活.这并不是说接口无法帮助您以多重继承允许的方式进行建模,但它实际上不是以任何形式或形式继承的,并且不应该被视为这样.它只是保证您的代码在您实现了所建立的所有方法之后才能工作.


Mar*_*ers 5

这很简单.您可以在一个类型中实现多个接口.例如,你可以有一个实现List,也是一个实例Deque(和Java一样...... LinkedList).

您无法继承多个父项的实现(即扩展多个类). 声明(方法签名)没有问题.