【问题标题】:In Java, when is an extension of a class at least as capable as the extended class? [closed]在 Java 中,什么时候类的扩展至少和扩展类一样有能力? [关闭]
【发布时间】:2015-07-28 05:50:45
【问题描述】:

我的问题比我在标题中所能描述的要复杂一些。然而,我不确定如何提出一个我能理解的适当笼统的问题。所以我会试着理解一些更具体的东西。

假设有一个公共抽象类A。还有B,A的直接公共子类。现在程序员需要定义一个子类C,还有一个问题是C应该从B派生还是直接派生来自 A.

B 具有 A 所没有的一些功能,而这些功能对于手头的工作肯定是必需的,而且除了需要之外什么都没有。但是如果 C 是直接从 A 派生的,那么该功能可以很容易地在 C 类中重新实现,只需大约 6 或 8 个简单的小方法。当然,C 将需要一些与 B 稍有不同或超出 B 的功能。程序员 Joe 说,既然事情发生了,那么在重新实现 B 的功能时,像往常一样有一些出错的机会,为什么要随身携带额外的代码,当 B 已经拥有几乎所有需要的东西时?但是程序员 Bill 做了一个简洁模糊的声明,即从 A 派生 C 可以提供“更大的控制”和更大的优化可能性。 Joe 注意到应用程序需要 B 的所有方法,他表明除了一两个之外的所有方法都可以按原样使用,他说如果需要,可以在类 C 中覆盖 B 的任何方法,以及任何新方法无论推导是直接还是间接,都可以轻松定义所需的内容。

Joe 注意到 A 只有公共方法和构造函数,并且它们都不是最终的,并且想要声称从 B 派生的 C 提供与直接从 A 派生的 C 一样多的控制权。

A 的访问控制属性及其方法和数据成员是否存在会影响答案的各种条件?

如果您需要具体案例来体现这个问题的一部分,请考虑 A 是 Android 的 BaseAdapter 类,B 是 Android 的 ArrayAdapter 类。我知道这个非常具体的问题已经在其他线程上得到了回答。但我想了解访问控制的本质以及会影响结果的类的其他声明属性。

【问题讨论】:

  • 既然“更大的控制”没有意义,这个论点听起来像是在浪费时间。重新实现许多已经很好地打包好的行为听起来也是浪费时间,尤其是没有任何令人信服的理由反对它。我投票结束这个主要是基于意见的。
  • 补充 Ted 所说的,这在很大程度上取决于您的设计以及您对设计原则的严格程度。您通常可以通过使用“is-a”哲学来判断一个类是否应该从另一个类派生,但其他一些东西,如 Liskov 替换原则和接口隔离原则也在其中发挥作用。总之,您应该更深入地研究继承原则,因为这将帮助您决定应该做什么。
  • 它并不完全基于意见......(至少在我看来;))我认为你正在为我们为什么拥有、使用和应该学习设计模式做出一个很好的例子。最后,这实际上取决于情况……取决于您是否必须实现使用基类功能的未来类……最后一件重要的事情始终是“优先组合而不是继承”。除此之外,我可以为您提供一些您应该研究的模式:模板、访问者、复合
  • 好吧,我试图通过给出一个相对于 A 和 B 的内置方法以及 C 所需的功能有些具体的示例来激发这个问题。但请考虑我的问题关于这两种方法对实现 C 和扩展 C 的可能性是否有或多或少的限制的客观意义。我的 OO 和 Java 经验并不广泛,但在我看来,它们在这方面并没有什么不同。如果这是正确的,那么接下来我想知道访问控制或其他属性的哪些条件(如果有的话)会带来这样的差异。
  • 约翰,即使这个问题被解释为寻求客观(非基于意见)的答案,我仍然会投票关闭它,因为它过于宽泛(参见the help center)。当我投票结束时,我实际上来回选择了哪个理由。这对 SO 来说不是一个好问题。在Quora 之类的论坛上,您可能会有更好的运气。

标签: java android oop inheritance class-design


【解决方案1】:

你的问题似乎有偏见,因为“程序员比尔”很简洁,他的反驳没有得到太多的重视或关注,而乔的立场相比之下却是详尽的。

因此,为了向 Bill 的 cmets 提供关于“控制和优化”的优点 - 首先,重用代码的反对论点是,使用现有方法为特定情况提供非最佳功能是常见的,通常不是问题。但是,它可以被视为草率,特定用例可能需要重新实现现有方法,以便针对特定目的对其进行优化。

在“扩展对象 B 并覆盖对象 B 的这些方法的实现”的上下文中执行此操作很容易使后来的原始作者或以后必须维护代码的程序员感到困惑或误导。为什么继承一个类和它的方法只是为了覆盖特定于它的实现?此外,当它最初提供的实现在其他地方有用但在这种情况下没有用时,为什么要这样做?继承您所知道的必要条件,复制您可以节省时间的内容,然后针对您面前的具体案例进行定制。

但是,如果这种情况涉及覆盖对象 B 的最少数量的方法,并且理想情况下适用于 B 的方法非常简单或根据其性质预期会被覆盖的情况,或者有大量方法可以不需要重新实现。在这些情况下,最好在讨论之前证明这一点,以便在需要时可以重构对象 B 以更好地支持继承和/或多态性。

这可能不好的是,这可能是两个程序员“过早优化”的情况 - 如果情况未经测试,使用对象 B 然后发现与该实现相关的问题并没有太大区别从使用对象 A,复制对象 B 代码,然后执行可能不必要或不需要的优化......两个程序员似乎都在推测结果,而没有一个论点或预期的性能问题/好处的坚实基础。在这种情况下,双方都没有坚定的立场来推进对话或根据所提供的信息提供坚定的建议。但给出的信息肯定偏向于乔的观察,不赞成比尔的简要说明。

因此,您对问题的描述可能会导致读者认为 A) 程序员 Joe 很懒惰并试图为其辩护,或者 B) 程序员 Bill 让他的自尊心干扰了实际操作。我试图避免这些情况中的任何一种,并解决程序员面临的现实问题,即面临需要思想开放与时间和资源短缺的困境,但请随时发表相应评论。

【讨论】:

  • 这个问题在我的现实生活中确实出现过,Bill 的说法与我提出的一样薄,他没有对乔的观点做出有意义的回应,也没有澄清他自己的观点,但似乎试图最后说乔可以随心所欲地做到这一点。如果 Joe 对使用这两种方法可以做什么和不能做什么有一个客观的理解,他最终会得出结论,根据 Java 的性质,间接扩展允许直接扩展允许的一切,并且他会忽略 Bill 的模糊主张和类似的主张未来。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-07-13
  • 1970-01-01
  • 1970-01-01
  • 2013-08-12
  • 1970-01-01
  • 2012-04-07
  • 2016-01-15
相关资源
最近更新 更多