如何在没有多重继承的情况下避免代码重复(即在 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
扩展抽象 ClassC
。
ClassD
扩展抽象 ClassE
扩展抽象 ClassF
它扩展了抽象 ClassC
。
[ClassC
是父类]
其中ClassA
和ClassD
具有一组相同的属性、getter 和setter。
我想避免代码重复(属性、getter、setter)。我还想避免编写不同的方法 doSomething(ClassA class, ...)
和 doSomething(ClassD class, ...)
,它们除了参数类型之外都相同。
如果这两个类直接继承自 ClassC
,我会让它们扩展一个包含所有 getter、setter 和属性的类,并将该类型传递给方法 doSomething(..)
。由于ClassA
和ClassD
不能扩展多个类,那么处理这种情况的最佳方法是什么?
【问题讨论】:
在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
并包含ClassA
和ClassD.
共有的方法
另一种选择是创建一个接口InterfaceAD
并让ClassA
和ClassD
实现它。使用接口作为函数的参数,如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 中)?的主要内容,如果未能解决你的问题,请参考以下文章