2009-12-19 118 views
4

所以你有一个接口和一个抽象类,它实现了接口中方法的一个子集。您还有一些类继承了抽象类,并给出了抽象类不提供的方法的实现。java中的抽象类和接口最佳实践

那么这里最好的做法是什么?我正在讨论的问题如下:

1)抽象类应该实现接口还是应该实现其子类?应该每班上课吗?在我看来,只有抽象类应该。当然,所有的类都可以实现这个接口,但这似乎是多余的,因为抽象的孩子会继承接口,因为它们扩展了抽象类。 2)鉴于抽象类实现了接口的一部分,它是否也为其未实现的方法声明了抽象方法?在我看来,这是对的,但从某种程度上看,这似乎是多余的,因为抽象的孩子们需要实施这些方法才能编译。

那么你最好的做法是什么?问题归结为:我们有一个接口来定义我们想要某些类所做的事情,我们在接口中定义了一些方法的子集来定义常见行为,并且我们有几种不同的方法来定义非常见的行为。解决这个问题的最好方法是什么?

回答

2

抽象类应该实现接口,并提供通用成员函数的具体实现。 IIRC不需要为它没有实现的元素声明抽象方法,因为这些被假定需要由子类实现。

8

在这里应该帮助你的原则DRY:不要重复自己(http://en.wikipedia.org/wiki/Don%27t_repeat_yourself)。

在这种情况下,DRY意味着你不应该做不必要的工作。

因此,对于第一个问题,抽象类应该实现接口,因为它可以避免在每个具体类上重复“实现X”子句。

至于第二个问题,在实现它的抽象类中重复接口方法没有意义。这是多余的工作。此外,当界面发展/变化时,您需要更改抽象类中的对应(抽象)方法,这很令人头疼。在某些时候,你会错过更新某些方法,具体的类将需要实现这些徒劳无功。

+0

+1,我会补充一点,如果我亲眼看到一个实现了Foo的具体类,并且扩展了AbstractFoo,那么我的第一个直觉就是Foo和AbstractFoo甚至可能没有关系。随着名字变得不那么明显,更多地引起混淆。 – PSpeed 2009-12-19 08:42:05

+1

接口并不意味着进化和改变... – TofuBeer 2009-12-19 09:30:13

+0

程序发展(因为您添加新功能,修复错误,无论如何),这会导致底层构件(类,接口,方法...)发生变化。例如,你可能会决定一个方法需要一个额外的参数,所以你必须在声明界面中改变它的签名。 – 2009-12-19 10:11:29

0

您是否比抽象类或其子类有更多的接口实现?你的设计需要界面吗?否则,界面对你的设计没有任何贡献,我建议你简单地摆脱它。

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

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

2

最灵活的方式来对这个方案是:

  1. 提供接口
  2. 提供一个实现该接口
  3. 提供的具体的类,要么从抽象类延伸或扩展抽象类从另一个类并实现接口
  4. 一直(除非你不能)将变量/参数/常量声明为接口而不是抽象类或具体类

使具体类实现接口没有意义(稍后)。 抽象类从接口重复抽象方法没有意义。

通过#4确保实现接口的所有类都可以使用 - 如果要使用抽象类,则不能使用实现接口但不扩展抽象类的类。

(后期)

为具有抽象类和具体类实现该接口的一个说法是,如果你要在以后更改具体类不再扩展抽象类,那么你可以忘了也实现了这个接口,在某些情况下,这个接口可能会破坏代码而不会引起编译器的抱怨。我不知道我对这个观点的看法。

1

接口方法是隐式抽象的,所以如果一个抽象类实现一个接口,就不需要满足抽象类中的接口契约。抽象接口在技术上是合法的,但也是多余的。只要所有子类都要实现接口,抽象类就可以实现接口,但抽象类不应该包含已实现的方法。

接口方法是特定于实现(对于实现类是唯一的),而抽象状态和行为是普遍的,或者在实现中共享。将接口方法作为通用功能来实现将是一个矛盾。

关键问题是您打算如何使用接口实现?如果基本接口除了定义一个附加约定之外没有用于其他任何东西,我会说简单地将抽象方法添加到抽象类中,否则接口是冗余开销。如果你发现一个你想要访问接口方法的用例,但不一定是通用的功能,那么接口可能是值得的。