如何在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 {}
如何在课堂上获得A
, B
和C
元素? 如果我使用接口来实现类,则会有很多重复的代码,内部类将不允许我覆盖现有的方法,以便保留A
, B
和C
的调用接口。
如何在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) 。 如果您符合这些限制,这将为您提供一个新的面向对象编程。