Java 多重继承

为了充分了解如何解决Java的多重继承问题,我有一个需要澄清的经典问题。

假设我有类,它有子类,我需要创建一个类,从和从既是鸟又是马。AnimalBirdHorsePegasusBirdHorsePegasus

我认为这是典型的钻石问题。从我能理解的,解决这个问题的经典方法是使 和 类接口并从中实现。AnimalBirdHorsePegasus

我想知道是否有另一种方法可以解决我仍然可以为鸟类和马创建对象的问题。如果有一种方法可以创造动物,那就太好了,但不是必需的。


答案 1

您可以为动物类(生物学意义上的类)创建接口,例如用于马和鸟类(我不是生物学家,因此这些术语可能是错误的)。public interface Equidaepublic interface Avialae

然后,您仍然可以创建一个

public class Bird implements Avialae {
}

public class Horse implements Equidae {}

以及

public class Pegasus implements Avialae, Equidae {}

从评论中添加:

为了减少重复代码,您可以创建一个抽象类,其中包含要实现的动物的大多数公共代码。

public abstract class AbstractHorse implements Equidae {}

public class Horse extends AbstractHorse {}

public class Pegasus extends AbstractHorse implements Avialae {}

更新

我想再补充一个细节。正如布莱恩所说,这是OP已经知道的事情。

但是,我想强调的是,我建议绕过接口的“多继承”问题,我不建议使用已经代表具体类型(如Bird)的接口,而是更多地代表一种行为(其他人指的是鸭子类型,这也很好,但我的意思是:鸟类的生物学类,Avialae)。我也不建议使用以大写字母“I”开头的接口名称,例如 ,这并不能说明为什么需要接口。这与问题的不同之处在于:使用接口构造继承层次结构,在有用时使用抽象类,在需要时实现具体类,并在适当时使用委派。IBird


答案 2

将对象组合在一起有两种基本方法:

  • 首先是继承。正如您已经确定的那样,继承的局限性意味着您无法在这里做您需要的事情。
  • 第二个是构图。由于继承失败,您需要使用组合。

其工作方式是你有一个动物对象。然后,在该对象中添加更多对象,以提供所需的属性和行为。

例如:

  • Bird 扩展 Animal implements IFlier
  • 延伸 动物工具 食草动物,四足动物
  • Pegasus扩展了Animal implements IHerbivore, IQuadruped, IFlier

现在看起来像这样:IFlier

 interface IFlier {
     Flier getFlier();
 }

所以看起来像这样:Bird

 class Bird extends Animal implements IFlier {
      Flier flier = new Flier();
      public Flier getFlier() { return flier; }
 }

现在,您拥有了继承的所有优点。您可以重用代码。您可以拥有IFlier的集合,并可以使用多态性的所有其他优点等。

但是,您也拥有组合的所有灵活性。您可以根据需要将任意数量的不同接口和复合支持类应用于每种类型的接口和复合支持类 - 并根据需要控制每个位的设置方式。Animal

策略 模式 组合的替代方法

根据您正在执行的操作和方式,另一种方法是让基类包含一个内部集合,以保留不同行为的列表。在这种情况下,您最终会使用更接近策略模式的东西。这确实在简化代码方面提供了优势(例如,不需要了解或),但是如果您不执行接口方法,您将失去许多多态性等优点。AnimalHorseQuadrupedHerbivore