是否可以抽象类替换接口?

时间:2010-01-23 22:11:05

标签: java oop interface abstract-class

在Java中,您可以创建仅包含抽象方法的抽象类。另一方面,您可以创建一个声明相同方法的接口。既然如此,你可以使用抽象类而不是接口吗?

11 个答案:

答案 0 :(得分:34)

并非总是如此:

  • 一个类只能扩展一个
  • 一个类可以实现多个接口

Sun docs进行更详细的比较:

  

抽象类与接口

     

与接口不同,抽象类可以包含非静态和最终的字段,并且它们可以包含已实现的方法。这些抽象类与接口类似,不同之处在于它们提供部分实现,将其留给子类来完成实现。如果抽象类只包含抽象方法声明,则应将其声明为接口。

     

可以通过类层次结构中的任何位置实现多个接口,无论它们是否以任何方式彼此相关。例如,可以考虑可比较或可克隆。

     

相比之下,抽象类最常被子类化以共享实现部分。单个抽象类由具有许多共同点(抽象类的实现部分)的类似类子类化,但也有一些差异(抽象方法)。

答案 1 :(得分:12)

在某些情况下,您可以使用抽象类而不是接口。但是,这样做几乎不是一个好主意。通常,您应该使用以下规则:

  1. 接口指定行为。
  2. 抽象类指定实现。
  3. 使用抽象类的另一个“问题”是你不能再实现mixins,也就是说你可以实现多个接口,但是你只能扩展一个抽象类。

答案 2 :(得分:11)

答案中缺少的一点是将实施界面的想法。

如果您的组件想要向其调用者返回抽象类型的实例,其中具体类型在内部定义并且对调用者隐藏,请使用接口< / strong>即可。相反,如果您的组件使用接受其调用者必须实现的抽象类型实例,抽象类是<通常是一个更好的选择。

预测进化并保持二进制兼容性提示这里的规模。使用抽象类,您可以添加方法,如果您提供基本实现,抽象类的现有实现将继续正常工作。使用接口,添加方法会破坏二进制兼容性,因为没有现有的实现可以继续正确编译而无需更改以定义新方法。

Apache Cactus projecta good discussion如何解决这些义务。

答案 3 :(得分:5)

要回答你的问题,是的你可以使用抽象类(不提供实现)而不是接口,但我会考虑这种不好的做法:

  • 你已经用完了继承的“一次性”(没有获得任何好处)。
  • 您不能从多个抽象类继承,但可以实现多个接口。

我建议在你希望提供类的部分实现的情况下更多地使用抽象类,可能会将某些行为委托给具体的子类实现。

答案 4 :(得分:4)

  • java中的类可以从多个接口继承,但只能从一个抽象类继承。

  • 接口无法定义任何代码,在抽象类中,您可以定义代码(即方法的默认行为)

答案 5 :(得分:4)

抽象类和接口是互补的。

例如,在创建API时,您需要向客户端提供接口,以便您可以始终完全更改实现,而不必更改其代码,并且用户在使用API​​构建时不依赖于实现但只是方法合同。

然后,您将拥有部分实现这些接口的抽象类,以便

  • 分享一些公共代码,可能在所有(或几乎所有)接口实现中使用,这很明显
  • 提供可以在“真实”实现中重写的默认行为,例如使用interfaces方法创建实现的文本表示的toString()方法
  • 在界面更改后保留实现兼容性,例如在界面中添加新方法时,还在抽象类中添加默认实现,以便扩展抽象类的实现(例如用户创建的实现)仍然有效没有变化

答案 6 :(得分:2)

接口更清洁,重量更轻。抽象类会让您严重依赖它,因为您无法扩展任何其他类。

答案 7 :(得分:1)

查看有趣的文章“Why extends is evil”,了解接口实现和类继承之间的差异(除了显而易见的多单一限制)

答案 8 :(得分:0)

抽象类是抽象的部分实现,而接口是抽象的完全实现。抽象类中的我们可以将方法声明和方法体放在一起。 我们不能创建抽象类(关联)的对象,并通过继承(而不是关联)重用该类。 默认情况下,在接口中,所有声明的变量都是静态final,所有方法都是公共的。

例如:在JDK中只有很少的抽象类,而HttpServlet就是Servlet中使用的其中之一。所以我们不能创建HttpServlet的对象,它只能通过继承来使用

答案 9 :(得分:0)

接口的主要用途是创建接口的引用并调用在运行时解析的特定类的方法。因此,创建接口的引用以调用该方法总是更好的主意。

答案 10 :(得分:-1)

接口只能保存抽象方法,接口也可以实现任何类的多个接口。但是抽象持有抽象和非抽象方法,抽象方法不能扩展到一个以上的类。