Java 为什么不应该';这些接口是否相互继承?

Java 为什么不应该';这些接口是否相互继承?,java,oop,inheritance,interface,Java,Oop,Inheritance,Interface,我发布了一篇关于我在有效Java中读到的接口和建议的文章。我得到了我想要的答案,一切都很好,直到今天下午我签署了SO,并留下一条评论说 这些接口不应相互继承 我问了为什么,但仍然没有得到答复。有人能解释为什么不允许这些接口继承吗?您将如何修复它,并且仍然保持答案中提供的相同功能 public interface GameObject { void viewDetails(); } public interface Weapon extends GameObject { void

我发布了一篇关于我在有效Java中读到的接口和建议的文章。我得到了我想要的答案,一切都很好,直到今天下午我签署了SO,并留下一条评论说

这些接口不应相互继承

我问了为什么,但仍然没有得到答复。有人能解释为什么不允许这些接口继承吗?您将如何修复它,并且仍然保持答案中提供的相同功能

public interface GameObject {
    void viewDetails();
}

public interface Weapon extends GameObject {
    void attack();
}

//A weapon is not the only item reloadable. A container could be refilled. 
public interface Reloadable extends GameObject {
    void replenish (final int amount);
}

我认为这些接口不继承的唯一原因是
GameObject
接口的简单性。它没有提供任何
toString
无法实现的功能。然而,这只是我游戏的开始阶段,
GameObject
当然会扩展

我认为你太担心自己设计的纯洁性了,以至于你只关心琐碎的细节,而不是高效地花时间,也就是说,写游戏

无论哪种方式都没有多大区别

通常,“游戏对象”(以及名称以“对象”结尾的任何对象)是一个类,如果需要的话是抽象的,但不是接口。将接口命名为“SomethingObject”的唯一原因是,该接口还扩展(或通过聚合公开)了
Closeable
AutoCloseable
)接口,这意味着任何对该接口有引用的人都可能破坏该接口。所以,如果你走这条路,剩下的问题都会得到简单的回答:接口武器可能不会扩展GameObject,因为接口可能不会扩展类,可重新加载也一样,我们完成了

现在,如果你坚持拥有一个“GameObject”界面,你仍然可以选择为每一个额外的特性扩展它,或者保持每个额外的特性独立,而不扩展“GameObject”。这两种方法都会奏效

如果你承诺,如果你以你所珍爱的一切的名义发誓,永远不会有一个不属于游戏对象的可重新加载的游戏,那么你可以继续拥有一个可重新加载的扩展游戏对象。但你真的需要吗?通常的做法是,我们更喜欢使用接口来增加继承树的分支程度,而不是将继承树变成一个图。(并不是说它从未发生过,但它很少发生。)所以,我们通常不会这样做。但如果你这样做,那就不是世界末日

还要注意,当我们从一个接口扩展到另一个接口时,我们(不总是,但是)通常会扩展名称。所以,你的武器应该是WeaponGameObject,你的可重新加载的武器应该是可重新加载的GameObject


还要注意的是,接口继承很少是必要的;您可以使可重新加载成为一个独立的接口(不扩展GameObject),也可以使可重新加载包含一个
GameObject getGameObject()
方法,从而实质上将两个实体链接在一起。然后,您的BFG9000ReloadableGameObject类可以实现Reloadable和GameObject,并实现
getGameObject()
as
返回此值

执行真正的域分析。你会发现有
补充
行为的东西,一个
可补充的
,不必是
武器
,补充时可能不在乎它是
游戏物品
车辆
也可能需要补充。也许像

public interface Weapon extends GameItem {
public class ChargeGun 
  implements Replenishable, Weapon {...

public class FlyingCarpet extends GameItem
  implements Replenishable, Vehicle {...
让类进行接口混合通常比让接口继承它们要好。这取决于领域和建模方式。尽你所能

gun.replenish();
不是


YMMV.

同意迈克的观点:可能不是你应该担心的舞台

对于游戏开发,通常避免使用面向对象的原则对“世界”进行建模。这是由于对象的强耦合和性能原因造成的。非常先进的游戏引擎不会为世界上的实体创建特定的类

如果您对更精细的细节感兴趣, 看看这个:

继承意味着“是一种”关系。因此,武器是一种游戏对象。根据你的模型,如果这是正确的,那就好了。但是如果一件武器有一个游戏对象,那么它应该有一个
GameObject getGameObject()
方法。如果两者都不是,它既不应该扩展,也不应该有
getGameObject()
方法。@AndyTurner-但在我的游戏中,它是一个游戏对象。从逻辑上讲,对我来说,物品和武器都是游戏对象。我知道如果它不是游戏项目,就不应该扩展,但这里不是这样,“如果根据你的模型这是正确的,那就好了”。这只是一个人的意见,他们不应该延长,而且没有人同意投赞成票。@AndyTurner-你可以投赞成票!谢谢你的回答。我使用了GameObject接口,因为如果它是一个抽象类,继承将非常深刻(Gun扩展GameObject,等等),并且有许多文章解释了为什么这是不好的。我不介意getter,但我最近遇到一个建议,说接口中的getter是代码气味(正如你指出的,我太担心它了。)根据我的游戏逻辑,这是有道理的。另一个评论回答说,但我不太确定我是否理解他的意思。这就是为什么Reloable没有扩展它(并非所有武器都是可重新装载的,例如剑)。可重新装载可应用于容器(盒子、杯子).你的例子似乎有点不对劲,第一个例子中的GameItem是一个接口,第二个例子中的GameItem是一个类,除非你是说实现。现在,补充需要一个数量。如果玩家升级并获得更大的弹药筒,那么他们现在可以重新加载10个子弹/弹药,那么补充怎么知道数量,如果它不是一个参数?只需在不带参数的情况下调用infull本身是不够的。前提是他们有盒带
replenish(Replenishable Replenishable);