【问题标题】:How many levels of inheritance [closed]多少级继承[关闭]
【发布时间】:2011-06-11 15:09:27
【问题描述】:

对于框架的继承层次结构的最大深度以及何时使用多级继承或将它们加入单个类中的准则,是否有任何最佳实践?

从社区和围绕 Java 的框架的角度来看,一些在 Java 世界中运行良好的已建立实践/示例的参考会很好地回答。

【问题讨论】:

  • 尽可能浅,尽可能深

标签: java inheritance frameworks


【解决方案1】:

当谈到最佳实践时,还应考虑性能(内存使用)。

当你的类层次很深(非抽象)时,它会使用更多的内存。就像创建 3 级继承的最后一个子对象的新对象将使用比 9 级继承更少的内存。 根据应用的性质,除了其他帖子之外,还可以考虑这一点。

【讨论】:

  • 面向对象和过程编码难道不能这么说吗?
【解决方案2】:

在我看来,每个派生类都是“它自己的一个类”,这个类的客户,包括子类)通常不应该打扰或感兴趣,在这个类和 @ 之间有多少类987654322@班级。

因此,我的回答是:不,让层次结构尽可能深,只要它有意义/看起来合乎逻辑。不要让层次结构的深度影响是否折叠两个类的决定。由于每个子类都是其基类的细化,因此我的经验表明,深度超过 5 或 6 个类很少有意义。


要明确一点:正如其他人指出的那样,您应该更喜欢组合而不是继承。不过,对我来说,这似乎回答了一个稍微不同的问题。


根据this article,标准Java API中的最大深度是9。

【讨论】:

  • 这完全是错误的。继承是众所周知的复杂性因素。
  • 你是说通过折叠类你得到一个不那么复杂的程序?
  • 任何代码复杂度指标都与类继承深度有关。根据 MS MSDN,层次结构越深,就越难理解特定方法和字段在哪里定义或/和重新定义
  • @Reza 任何概念都可以发挥到极致,我们不需要 MSDN 来告诉我们。这就是为什么aioobe只要它有意义/看起来合乎逻辑
  • @Reza 另外,如果您强调维护方面的技术困难,任何体面的 IDE 都会向您显示重新定义方法的子类。
【解决方案3】:

您可能正在寻找一个很好的规则,例如“不超过 5 级继承”,但我真的怀疑是否存在这样的规则。对象通常模拟现实世界的实体,而所有这些实体的社区从未就规则达成一致(据我所知)......

一个“最佳实践”无疑是:优先考虑组合而不是继承。遵循此准则:定义一个接口和实现,而无需进一步的超类。所有常见的字段和方法都带有行为和strategies

另一方面,我们有时会对已经具有深层实体层次结构的现实世界实体或结构进行建模。 动物分类就是一个例子或algebraic structures。对此类现有结构进行建模的框架将需要较深的类层次结构,因为它应该遵循现实世界以便易于理解。

【讨论】:

  • 当然,动物分类作为继承结构存在问题。
  • 我讨厌到处看到这种优先组合优于继承,超出上下文。你在重要的地方使用组合,在重要的地方使用继承。真正的规则应该是不要使用继承作为代码共享机制。
  • 如果超类中的至少一个方法对子类没有意义。您应该替换组合的继承。例如,考虑从 List Class 继承的 Stack Class。即使它们具有相似的操作并且列表可以用作堆栈的存储,List 类中的几个方法对堆栈类没有意义,并且在继承的情况下会出现在堆栈公共接口中,这真的很尴尬.在这种情况下,优先组合而不是继承将是有益的,至少你会摆脱那种气味。
【解决方案4】:

没有关于最大继承深度的最佳实践。当涉及到 java(以及任何 OO 语言)中的继承时,这是经验法则,而不是体积。

1_ 在实现继承之前检查“is a”关系是否为真。充电器是汽车。 (所以继承很好)。如果你这样做,那么无论如何你都不会得到巨大的继承树。 (轮子不是车,所以这里的继承是错误的)

2_ 如果“是”关系失败或者您有歧义,那么可能的继承不是方法。您需要确定类之间的共性并使用组合。(将公共代码重构为新类)。

3_如果你想建立一个类型层次结构,那么你应该使用接口继承(类型)而不是类级继承。 (可能其中一些陈述需要更多解释,但为此您可能需要拿起一些书。)

【讨论】:

    【解决方案5】:

    据我所见(注意:这不是官方意见,只是我的观察),3-4 是合理的最大值。

    另外,请记住 Effective Java 中的一个重要部分:

    组合优于继承

    【讨论】:

      【解决方案6】:

      一般规则是层次结构越深,就越难理解特定方法和字段在哪里定义或/和重新定义。

      但除了继承之外,您还需要注意其他一些因素,以保持代码复杂性可控。

      最好的方法是使用代码度量工具并尝试在不同因素(代码行、类解耦和...)之间取得平衡

      【讨论】:

        【解决方案7】:

        最好的是每个班级都处理一堆类似的事情。
        此类中的每个方法都处理一个动作/行为。

        看看这个来自 DZone 的 refcard: http://refcardz.dzone.com/assets/download/refcard/54c22c8b0a53591ea9e0504fdfd4bada/rc130-010d-designing-quality_0.pdf

        【讨论】:

        • 一大堆类似的东西?你不喜欢单一职责原则?
        【解决方案8】:

        您应该首先考虑您正在编写的代码的清晰度。具有更高层次的深度会使代码更易于阅读和维护,还是会使代码更难。很大程度上取决于您要解决的问题。

        正如其他海报所建议的那样,您可以使深度太浅或太深。这是一个金发姑娘问题恕我直言。

        【讨论】:

          【解决方案9】:

          我认为,从维护的角度来看,您可以管理的继承层次结构越浅越好。通过多个层级向下跟踪错误,然后必须弄清楚应该在哪个层级修复它们可能是一个棘手的问题。

          【讨论】:

          • 我会提出完全相反的观点:通过将类折叠成更少、更大的类,会使调试变得更加困难。
          • @aioobe - 这是真的,但也有可能走得太远,把事情分割得太远,在这种情况下组合会更有利,而不是继承。我正在研究一些发生这种情况的复杂层次结构......
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多