面向对象编程中的一个典型问题是菱形问题。我有父类 A 和两个子类 B 和 C。A 有一个抽象方法,B 和 C 实现它。现在我有一个子类D,它继承了BandC.现在的钻石问题是,D应该使用什么实现,B的实现还是C的实现?
人们声称 Java 不存在钻石问题。我只能通过接口进行多重继承,并且由于它们没有实现,所以我没有钻石问题。这是真的吗?我不这么认为。见下文:
[删除车辆示例]
钻石问题是否总是导致类设计不良的原因,并且是程序员和编译器都不需要解决的问题,因为它本来就不应该存在?
更新:也许我的例子选择不当。
看这张图片
(source: suffolk.edu http://cartan.cas.suffolk.edu/oopdocbook/opensource/src/multinheritance/PersonStudentTeacher.png)
当然,您可以在 C++ 中将 Person 设为虚拟,这样内存中就只有一个 person 实例,但恕我直言,真正的问题仍然存在。您将如何为 GradTeachingFellow 实现 getDepartment() ?考虑一下,他可能是一个系的学生,而在另一系任教。因此,您可以返回一个部门,也可以返回另一个部门;这个问题没有完美的解决方案,并且没有实现可以被继承(例如,Student 和 Teacher 都可以是接口)这一事实对我来说似乎并不能解决问题。
您所看到的是如何违反里氏替换原则 http://en.wikipedia.org/wiki/Liskov_substitution_principle使得拥有一个有效的、逻辑的面向对象结构变得非常困难。
基本上,(公共)继承应该只缩小类的用途,而不是扩展它。在这种情况下,通过继承两种类型的车辆,您实际上是在扩展目的,并且正如您所注意到的,它不起作用 - 水上车辆的移动与公路车辆的移动应该非常不同。
您可以在两栖车辆中聚合水上车辆和地面车辆对象,并从外部决定两者中的哪一个适合当前情况。
或者,您可以决定“车辆”类是不必要的通用类,并且您将为两者提供单独的接口。但这并不能单独解决你的两栖车辆的问题 - 如果你在两个界面中都调用移动方法“move”,你仍然会遇到麻烦。所以我建议使用聚合而不是继承。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)