Java中抽象类和接口的最佳实践

4

那么,你有一个接口和一个抽象类,该抽象类实现了接口中的一部分方法。你还有一些继承自这个抽象类的类,并给出了抽象类未提供的方法的实现。

那么在这里有什么最佳实践?我谈论的是像以下问题:

1)应该由抽象类实现接口还是应该由其子类实现?每个类都应该吗?我认为只有抽象类应该实现接口。当然,所有类都可以实现接口,但这似乎是冗余的,因为抽象类的子类将“继承”接口,因为它们扩展了抽象类。

2)考虑到抽象类实现了接口的某些部分,它是否也应该声明未实现的抽象方法?在我看来,这是正确的,但从某种程度上说,这似乎是多余的,因为抽象类的子类将需要实现这些方法才能编译。

那么你对最佳实践的论据是什么?这个问题归结为:我们有一个接口定义了我们希望一些类做什么,我们有接口中定义的一部分方法来定义公共行为,我们有几种不同的方式来定义非公共行为。该如何布局最佳?

5个回答

9
这里的原则是DRY:不要重复自己(http://en.wikipedia.org/wiki/Don%27t_repeat_yourself)。
在这个上下文中,DRY意味着你不应该做不必要的工作。
所以对于你的第一个问题,抽象类应该实现接口,因为它可以避免在每个具体类中重复使用“implements X”语句。
至于第二个问题,在实现接口的抽象类中重复接口方法是没有意义的。这是多余的工作。此外,当接口发生变化时,你需要在抽象类中更改对应的方法,这很麻烦。在某些情况下,你会忘记更新某些方法,导致具体类白白实现这些方法。

+1,如果我亲眼看到一个具体的类实现了Foo并且扩展了AbstractFoo,我的第一反应可能是Foo和AbstractFoo甚至可能没有关系。当名称变得不那么明显时,会增加更多的混乱。 - PSpeed
程序会不断发展(因为您添加新功能,修复错误等),这导致底层工件(类、接口、方法等)发生变化。例如,您可能决定某个方法需要一个额外的参数,因此必须更改其在声明接口中的签名。 - Itay Maman

2

这个抽象类应该实现接口,并提供常见成员函数的具体实现。如果我没记错的话,它不需要声明未实现的抽象方法,因为子类会自行实现它们。


2
最灵活的编程方式是:
  1. 提供接口
  2. 提供实现接口的抽象类
  3. 提供具体类,这些类要么从抽象类继承,要么从另一个类继承并实现接口
  4. 除非你无法这样做,否则始终将变量/参数/常量声明为接口,而不是抽象类或具体类
没有必要让具体类实现接口(稍后会有更多说明)。 没有必要让抽象类重复接口中的抽象方法。
通过执行步骤#4,您确保可以使用实现接口的所有类-如果您使用抽象类,则未扩展抽象类但实现接口的类不能使用。
(稍后部分)
让抽象类和具体类都实现接口的一个论点是,如果您稍后更改具体类以不再扩展抽象类,则可能会忘记还要实现接口,在某些情况下,这可能会破坏代码而不会导致编译器发出警告。 我不知道我对这个论点的感觉如何。

1

接口方法是隐式抽象的,因此如果一个抽象类实现了一个接口,则没有必要在抽象类中满足接口合同。 抽象接口在技术上是合法的,但也是多余的。 只要所有子类否则都会实现接口,抽象类就可以实现接口,但是抽象类不应包含已实现的方法。

接口方法是实现特定的(唯一的实现类),而抽象状态和行为旨在成为共享的或共享的。 实现接口方法作为常见功能将是矛盾的。

关键问题是您计划如何处理接口实现? 如果基本接口除了定义其他合同之外没有用途,我会说只需向抽象类添加抽象方法,否则接口是多余的开销。 如果您找到了一个使用案例,您想要访问接口方法,但不一定需要共享功能,则可能值得使用接口。


0

你是否拥有比抽象类或其子类更多的接口实现?你的设计需要这个接口吗?否则,接口对你的设计没有任何贡献,我建议你干脆抛弃它。

当涉及到你的明确问题时,抽象类应该实现接口。继承抽象类的类不应该实现接口。

你不应该在已经在接口中声明的抽象方法中冗余地声明在抽象类中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接