如何在没有多重继承的情况下避免代码重复(即在 java 中)?

Posted

技术标签:

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

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

假设我有以下情况:

ClassA 扩展抽象 ClassB 扩展抽象 ClassCClassD 扩展抽象 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 等可以解决的所有相同问题。 你可以使用组合代替继承 【参考方案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 实现,尽管这可能会让人感到困惑)

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

【讨论】:

以上是关于如何在没有多重继承的情况下避免代码重复(即在 java 中)?的主要内容,如果未能解决你的问题,请参考以下文章

重构以避免在使用抽象类而不是接口时进行多重继承

python多重继承

什么是Mixin

C# 应该有多重继承吗? [关闭]

java中的多重继承是啥意思?

为啥在多重继承的情况下QObject需要是第一个