当前位置:  开发笔记 > 编程语言 > 正文

钻石问题能真正解决吗?

如何解决《钻石问题能真正解决吗?》经验,为你挑选了4个好方法。

OO编程中的典型问题是钻石问题.我有父类A,有两个子类B和C.A有一个抽象方法,B和C实现它.现在我有一个子类D,它继承了B C.钻石问题现在,D使用什么实现,B或C之一?

人们声称Java不知道钻石问题.我只能有接口的多重继承,因为它们没有实现,我没有钻石问题.这是真的吗?我不这么认为.见下文:

[删除车辆示例]

钻石问题总是导致糟糕的类设计,也不是程序员和编译器需要解决的问题,因为它首先不应该存在?


更新:也许我的榜样选择不当.

看到这个图像

钻石问题
(来源:suffolk.edu)

当然你可以用C++创建Person虚拟,因此你只有一个人在内存中的实例,但真正的问题仍然存在恕我直言.你如何为GradTeachingFellow实现getDepartment()?考虑一下,他可能是一个系的学生,另一个系教学.所以你可以退回一个部门或另一个部门; 对于这个问题没有完美的解决方案,并且没有实现可以继承(例如学生和教师都可以作为接口)似乎并没有解决问题.



1> Joris Timmer..:

你所看到的是违反Liskov替代原则的方式如何使得一个有效的,逻辑的面向对象结构变得非常困难.
基本上,(公共)继承应该只缩小类的目的,而不是扩展它.在这种情况下,通过继承两种类型的车辆,您实际上是在扩展目的,并且正如您所注意到的那样,它不起作用 - 水上交通工具的移动应该与公路交通工具的移动非常不同.
您可以在水陆两用车辆中汇总水上交通工具和地面车辆对象,并在外部决定哪两个适合当前情况.
或者你可以决定"车辆"类是不必要的通用,你将有两个单独的接口.这并不能解决你自己的两栖车辆的问题 - 如果你在两个界面中调用移动方法"移动",你仍然会遇到麻烦.所以我建议聚合而不是继承.


使用"IS A"作为继承的助记符是有缺陷的,这实际上是特别注意纠正Liskov替换的全部原因.经常引用的例子是使用面积方法的正方形和矩形,其中获得正确的Liskov替换并不是微不足道的.

2> Douglas Leed..:

C#有明确的接口实现来部分处理这个问题.至少在你有一个中间接口(它的一个对象......)的情况下

然而,可能发生的事情是AmphibianVehicle对象知道它目前是在水上还是陆地上,并做正确的事情.



3> Olivier..:

在您的示例中,move()属于Vehicle接口并定义合同"从A点到B点".

GroundVehicleWaterVehicle扩展Vehicle,他们含蓄地继承了这个合同(比喻:List.contains从继承其合同Collection.contains-如果指定的不同的东西想象!).

因此,当具体AmphibianVehicle实施时move(),它真正需要尊重的合同是Vehicle.有一颗钻石,但无论你是考虑钻石的一面还是另一面(或者我称之为设计问题),合同都不会改变.

如果您需要"移动"的合同来体现表面的概念,请不要将其定义为不对此概念进行建模的类型:

public interface GroundVehicle extends Vehicle {
    void ride();
}
public interface WaterVehicle extends Vehicle {
    void sail();
}

(比喻:get(int)合同是由List界面定义的.它不可能由定义Collection,因为集合不一定是订购的)

或者重构您的通用接口以添加概念:

public interface Vehicle {
    void move(Surface s) throws UnsupportedSurfaceException;
}

我在实现多个接口时遇到的唯一问题是来自完全不相关的接口的两个方法碰巧碰撞:

public interface Vehicle {
    void move();
}
public interface GraphicalComponent {
    void move(); // move the graphical component on a screen
}
// Used in a graphical program to manage a fleet of vehicles:
public class Car implements Vehicle, GraphicalComponent {
    void move() {
        // ???
    }
}

但那不会是钻石.更像是一个颠倒的三角形.



4> Steven Evers..:

人们声称Java不知道钻石问题.我只能有接口的多重继承,因为它们没有实现,我没有钻石问题.这是真的吗?

是的,因为你在D中控制接口的实现.两个接口(B/C)之间的方法签名是相同的,并且看到接口没有实现 - 没有问题.

推荐阅读
echo7111436
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有