【问题标题】:How do I avoid code duplication without multiple inheritance (i.e. in java)?如何在没有多重继承的情况下避免代码重复(即在 java 中)?
【发布时间】:2017-01-25 05:06:35
【问题描述】:

(我是一名新手开发人员,仍在学习最佳实践和 java - 任何帮助/指导将不胜感激,谢谢!)

假设我有以下情况:

  • ClassA 扩展抽象 ClassB 扩展抽象 ClassC
  • ClassD 扩展抽象 ClassE 扩展抽象 ClassF 它扩展了抽象 ClassC

[ClassC是父类]

其中ClassAClassD 具有一组相同的属性、getter 和setter。

我想避免代码重复(属性、getter、setter)。我还想避免编写不同的方法 doSomething(ClassA class, ...)doSomething(ClassD class, ...),它们除了参数类型之外都相同。

如果这两个类直接继承自 ClassC,我会让它们扩展一个包含所有 getter、setter 和属性的类,并将该类型传递给方法 doSomething(..)。由于ClassAClassD 不能扩展多个类,那么处理这种情况的最佳方法是什么?

【问题讨论】:

  • 在java中你可以使用interfaces
  • 你有一个具体的例子来说明为什么你会允许交互图变得这么深吗?
  • 所以 D 是 E 是 F 是 C。这有点过多地使用继承。
  • 考虑使用委托而不是继承。也就是说,A has a B 关系通常可以解决A is a B 等可以解决的所有相同问题。
  • 你可以使用组合代替继承

标签: java abstract-class multiple-inheritance extends


【解决方案1】:

首先,让我说,当一个(他们自己承认的)新手开发人员关心这类问题时,这是非常好的。大多数开发人员避免思考,只是编写大量无脑代码,因为这是他们知道可行的路径,无需思考。 (而且必须维护所有这些代码似乎从来都不是什么大问题,因为......它位于遥远的未来!)

作曲

大多数Java商店遵循的方法是避免继承,因为它太复杂了,而是使用组合,这也导致必须编写大量无脑代码。通常情况下,这样做是因为将“优先组合优于继承”的建议误解为“仅使用组合,从不使用继承”。

我不确切地知道你在做什么,所以我不能建议你放弃你正在做的事情并改用组合。我只是假设你有你使用继承的理由,所以,我不会在这里写更多关于组合的内容;如果您有兴趣了解有关组合的更多信息,可以轻松搜索“组合与继承”一词。

接口继承

从您描述的类结构来看,您似乎处于可以从使用接口中受益匪浅的典型情况:在 Java 中,一个类不能扩展多个类,但它可以实现多个接口。

如果两个接口都定义了像reticulate( Spline s ) 这样的方法,并且一个类实现了这两个接口,那么它可以提供reticulate() 的单个实现,并且它将满足这两个接口。 (这样做的缺点是,如果您希望您的类为每个接口提供不同的 reticulate() 实现,那么您将陷入困境;这是无法做到的。)

此外,Java 支持接口中的default 方法,这意味着您需要提供的某些功能可以直接编码到接口中,以便实现类从接口继承此功能,因此没有重新实现它。

【讨论】:

  • 您可能不需要避免继承:Java 已经允许在接口中使用multiple inheritance of method implementations
  • @AndersonGreen 你是对的,我修改了我的答案以考虑到这一点。如果您认为可以更好地解决您提出的问题,请告诉我。
【解决方案2】:

我不确定我是否正确理解了您的问题,但我会试一试。与其创建多个抽象类,不如创建多个接口。然后创建一个实现这两个接口的类。 Java 允许实现多个接口,但不能从多个类扩展。

【讨论】:

    【解决方案3】:

    在我看来,拥有一个ClassAD 可能很有用,它扩展了ClassC 并包含ClassAClassD. 共有的方法

    另一种选择是创建一个接口InterfaceAD 并让ClassAClassD 实现它。使用接口作为函数的参数,如doSomething(InterfaceAD i)

    【讨论】:

      【解决方案4】:

      你可以这样做

      class M
      
          class A extends B
      
              inherit B's stuff
      
          class D extends E
      
              inherit E's stuff
      
          A b = new A();
          D d =  new D();
          // or use anonymous classes
      
           M has access to everything in A and D,
          therefore M has access to A and D inheritable assets.
      

      现在在 C 类中添加你常用的方法

      【讨论】:

        【解决方案5】:

        你真的应该在这里讨论抽象类。您将如何测试 A、B、C、D、E 和 F?
        这将包括许多由 C 实现的任何方法的重复测试用例(因为它也被所有其他类使用)等等。

        如前所述,真正讨论组合而不是继承。 A 可能有一个 C,并通过方法。它也可能有 Q,D 也可能有。
        然后 D 和 A 都可以实现相同的接口(可能也由 Q 实现,尽管这可能会让人感到困惑)

        请注意,我不喜欢抽象类,而是更喜欢使用组合和/或策略。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-07-08
          • 2020-02-04
          • 2013-04-10
          • 1970-01-01
          • 2011-04-11
          • 1970-01-01
          相关资源
          最近更新 更多