在Java接口中,如何*不*使用从父接口继承的特定方法?
我有三个接口的层次结构,祖父母、父母和孩子父级和子级有一个方法“add”,它需要在子级中使用不同的输入参数。虽然在子级中添加所需的签名没有问题,但继承的方法将毫无意义,因此有没有办法不将其包含在子级中其他方法都很好。 也许,为了实现我想要的,我可以完全改进设计,因此我将简要介绍接口的内容: 我收集由时间和数值组成的仪表读数。祖父母界面仅用于一次阅读。我也有一些表示连续阅读的类(一个系列),还有一个包含在同一时间段内运行的多个系列(我们称之为表)在Java接口中,如何*不*使用从父接口继承的特定方法?,java,interface,Java,Interface,我有三个接口的层次结构,祖父母、父母和孩子父级和子级有一个方法“add”,它需要在子级中使用不同的输入参数。虽然在子级中添加所需的签名没有问题,但继承的方法将毫无意义,因此有没有办法不将其包含在子级中其他方法都很好。 也许,为了实现我想要的,我可以完全改进设计,因此我将简要介绍接口的内容: 我收集由时间和数值组成的仪表读数。祖父母界面仅用于一次阅读。我也有一些表示连续阅读的类(一个系列),还有一个包含在同一时间段内运行的多个系列(我们称之为表) 该表可以被视为一个系列(与时间轴正交地聚合值),而
该表可以被视为一个系列(与时间轴正交地聚合值),而表和系列都可以被视为单个读取(提供不同聚合方式的实现),因此继承。这似乎很好,但是对于add方法。(我可以向序列中添加一个点,但对于表,我需要一个附加参数来告诉我它属于哪个序列。)接口就是一个契约。这意味着任何实现该接口的东西都必须实现定义的方法。从技术上讲,您可以将其实现为一个虚拟方法(没有主体,只是返回,等等),但据我所知,它必须被实现。也许将接口继承全部中断是有意义的。只需为特定类型的行为提供特定的接口。实现这些接口的任何类都可以选择有意义的类,而不必担心实现没有意义的方法。不,您不能避免继承方法,因为这样做会违反规则 实际上,您可以让实现抛出一个
UnsupportedOperationException
,但这会非常糟糕
您不能用序列的某种默认值实现继承的方法吗?您可以始终将该方法实现为空,例如:
class A implements B{ void add(A) { /*Goes Nowhere Does Nothing*/ return;} }
但实际上,这不是一个好主意。一个更好的解决方案是,您的祖父母、父母和孩子都是同一个类,并且有两个额外的方法-hasParent():boolean和hasChild():boolean。这有一个利斯科夫替代兼容的变化,以及更清洁的设计的好处 继承的问题在于,对语言机制的关注使人们考虑的是实现而不是语义 当B从A继承时,这意味着B的每个实例也是A的实例。在OOP中,作为某物的实例通常意味着您应该对其方法做出合理的响应,至少支持它们的消息 如果您认为B不应支持A的其中一条消息,那么就我而言,您有两种选择: 错误-抛出一个“未实现”的异常,就像在collections框架中一样。然而,在我看来,这是糟糕的形式
好-接受B不是a的类型,避免继承,或者重新构造它(例如,使用组合和/或接口),这样您就不必重写代码,但不必使用子类型关系。如果你的应用程序可以长期使用,你就不想在层次结构中出现语义问题。谢谢你让我走上正轨,我对我发现最有用的帖子进行了投票。由于我的解决方案是受这些帖子的启发而提出的,但并未发布,因此我将与大家分享我的决定: 由于层次结构的灵感来自于数据的查看方式,而问题出现在如何添加数据的语义上,因此我将把series和table的接口分为读接口和写接口。写接口彼此无关,读接口可以继承而不发生冲突
我将创建这个wiki,以防有人想在此基础上进行扩展。您可能想看看代码的味道。+1以获得关于为什么接口不是这样工作的最终答案。我同意对试图按照合同行事的人提出例外是令人讨厌的。我将研究安迪·怀特的解决方案建议。永远+1。据我所知,你的问题是,汉诺,最好使用组合而不是继承。这里的更多细节:+1对于链接,该网站似乎对一些经典场景非常有用。我喜欢代码气味(好吧,这个想法——而不是气味本身)——指出错误往往比就什么好进行理论辩论更容易。