如何在Java中实现多重inheritance

我正在使用Java中的某个API库。 它有一个基类A,以及B和C,它们都扩展A. B&C提供类似但不同的function,所有三个类都在库中。

public abstract class A { virtual foo(); } public class B extends A {} public class C extends A {} 

如何在课堂上获得ABC元素? 如果我使用接口来实现类,则会有很多重复的代码,内部类将不允许我覆盖现有的方法,以便保留ABC的调用接口。

如何在Java中实现多重inheritance?

编辑:感谢编辑George,现在更清楚了,忘了提一个关键要求:我的类必须以A为基础,以便它们可以通过平台API进行管理。

回顾一下,你有:

 class A { public void foo() {} } class B extends A { public specificAMethod() {} } class C extends A { public specificCMethod() {} } 

上述类位于您无法访问或修改的库中。 您希望在第三个类D中获得B和C的行为,就好像它可以写:

 class D extends B, C { } 

对?

那么使用B和C而不是inheritance呢? 你真的需要inheritance吗? 你想调用私人B和C方法吗?

 class D { private B b; private C c; } 

如果采用“首选组合而非inheritance”的一般方法,您可能会发现其中一个或两个类实际上不应该实际上是“inheritance”。 在这两种情况下,这些类都有严格的“is-a”关系吗? 如果你可以大声说“Has-a”并且它听起来不傻,你可能想要合成。

例如,如果你正在实施一副牌,那3个黑桃是一个3并且它是一个铲子,但你也可以把它想象成它有一个3并且它有一个套装(铲子)。 既然你可以这样想,你应该更喜欢has-a解释和使用组合。

尝试远离inheritance树而不是几个对象 – 如果你觉得想要使用多重inheritance,试着解决它。 这种情况下,Java会强迫您通过不提供function来设计您的代码更具可读性(但不可否认,当您真正需要它时,它就不存在而且可能会受到伤害!某些级别的混合将是尼斯)。

听起来你想扩展A – 调用它D – 覆盖它的foo(),然后有新的子类E&F扩展D并添加它们自己的function。

您可能会考虑提取通用接口并重用它们。 具有重构function的良好IDE将使其易于操作。

Java中不可能有多类inheritance,但是您可以对接口使用多inheritance。 使用委托模式,您可以将其他几个类的行为合并为一个。

COM中应用了完全不同的方法:所有对象都inheritance自IUnknown,它具有可以转换为Java的方法:

 Object queryInterface(Class clazz) 

这种方法最简单的实现可以是:

 if(clazz.isAssignableFrom(this.getClass())) return this; else return null; 

单inheritance不起作用的地方,只需添加:

 else if(class == SomeClass.class) { return something; } else ... 

这样,即使是最复杂的多重inheritance案例也可以解决,并且您可以完全控制返回的内容和时间,因此您可以避免许多与C ++等语言的“经典”多重inheritance问题,例如fork-join问题。

从Java 1.8开始,您可以使用具有默认方法的接口。 它非常方便,我倾向于使用它。 也支持协变返回类型 。 有一个fiew restricktions(见下文),但你不必自己实现inheritance,让编译器为你工作。

 public interface A { default A foo() { return this; } } public interface B extends A { @Override default B foo() { return this; } } public interface C extends A { @Override default C foo() { return this; } } public interface D extends B, C { @Override // if the return type does not implement B and C // the comiler will throw an error here default D foo() { return this; } } 

请注意,但请注意,由于其静态接口,您无法调用super.foo或定义字段或私有成员(直到Java 9) 。 如果您符合这些限制,这将为您提供一个新的面向对象编程。