关于java:是否可以抽象类替换接口?

Do/can abstract classes replace interfaces?

本问题已经有最佳答案,请猛点这里访问。

在爪哇中,可以创建只包含抽象方法的抽象类。另一方面,您可以创建一个声明相同方法的接口。既然如此,你能用抽象类代替接口吗?


并非总是如此:

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

Sun Docs进行了更详细的比较:

Abstract Classes versus Interfaces

Unlike interfaces, abstract classes can contain fields that are not static and final, and they can contain implemented methods. Such abstract classes are similar to interfaces, except that they provide a partial implementation, leaving it to subclasses to complete the implementation. If an abstract class contains only abstract method declarations, it should be declared as an interface instead.

Multiple interfaces can be implemented by classes anywhere in the class hierarchy, whether or not they are related to one another in any way. Think of Comparable or Cloneable, for example.

By comparison, abstract classes are most commonly subclassed to share pieces of implementation. A single abstract class is subclassed by similar classes that have a lot in common (the implemented parts of the abstract class), but also have some differences (the abstract methods).


在某些情况下,可以使用抽象类而不是接口。然而,这样做并不是一个好主意。一般来说,您应该使用以下规则:

  • 接口指定行为。
  • 抽象类指定实现。
  • 使用抽象类的另一个"问题"是,您不能再实现混合,也就是说,您可以实现多个接口,但是您只能扩展一个抽象类。


    这里的答案缺少一点,那就是谁将实现接口。

    如果组件希望将抽象类型的实例返回给其调用方,其中具体类型是在内部定义的,并对调用方隐藏,请使用接口。相反,如果组件使用或接受其调用方必须实现的抽象类型的实例,则抽象类通常是更好的选择。

    预测进化和维护二进制兼容性提示了这里的规模。使用抽象类,可以添加方法,如果提供基本实现,则抽象类的现有实现将继续正常工作。对于接口,添加方法会破坏二进制兼容性,因为没有任何现有的实现可以在不更改定义新方法的情况下继续正确地编译。

    阿帕奇仙人掌项目对如何解决这些义务进行了很好的讨论。


    要回答您的问题,可以使用抽象类(不提供实现)而不是接口,但我认为这是一个坏做法:

    • 你已经用完了遗产的"一枪"(没有任何好处)。
    • 不能从多个抽象类继承,但可以实现多个接口。

    我更主张在希望提供类的部分实现的情况下使用抽象类,可能会将一些行为委托给具体的子类实现。


    抽象类和接口是互补的。

    例如,在创建API时,您将希望向客户机提供接口,以便您可以始终完全更改实现,而他不必更改其代码,并且用户在使用API构建时不依赖实现,而只依赖方法契约。

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

    • 共享一些公共代码,这些代码可以在接口的所有(或几乎所有)实现中使用,这是显而易见的。
    • 提供可在"real"实现中重写的默认行为,例如,使用接口方法创建实现的文本表示形式的toString()方法
    • 在接口更改后保持实现的兼容性,例如,在接口中添加新方法时,还将在抽象类中添加默认实现,这样扩展抽象类的实现(例如用户所做的那些实现)仍然可以不做任何更改地工作。

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

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


    界面更干净,重量更轻。抽象类使您严重依赖它,因为您不能扩展任何其他类。


    看一看有趣的文章"为什么扩展是邪恶的",了解接口实现和类继承之间的区别(除了明显的多个单一限制之外)


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


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

    例如:JDK中抽象类很少,而httpservlet就是其中一个在servlet中使用的抽象类,所以不能创建httpservlet对象,只能通过继承来使用。


    接口只能容纳抽象方法,也可以实现多个接口到任何类。但是抽象包含抽象方法和非抽象方法,抽象方法不能扩展到多个类。