关于java:何时使用抽象类或接口?

When to use abstract class or interface?

为什么要创建抽象类或接口类,或者何时应该使用抽象类或接口类?


当您只想声明类必须具有哪些方法和成员时,使用接口。任何实现接口的人都必须声明和实现接口列出的方法。

如果您还希望有一个默认实现,请使用抽象类。扩展抽象类的任何类都必须只实现其抽象方法和成员,并且将具有抽象类的其他方法的一些默认实现,您可以重写或不重写这些方法。

--编辑-忘了提,Earwicker提醒我

最后,您可以实现任意多的接口,但只能扩展一个类(是否抽象)。在选择之前要记住这一点。


关键的区别在于,一个类中可以有多个接口,但只能有一个抽象类。这是因为抽象类还可以定义存储数据的字段,而接口不能。


抽象类是一个类,它至少有一个抽象方法,或者您也可以使所有方法都成为抽象的。显然,它不能被实例化。必须从抽象类继承并在继承类(即扩展抽象类的类)中实现抽象方法。

接口根本不是类(所以不要调用它们接口类)。接口定义方法的签名,而不进行任何实现。接口也没有成员字段。如果在类中实现接口,则必须为接口提供的所有方法提供实现。

为一些可能有完全不同实现的东西定义一个通用的API是有意义的。抽象类对于基本上相同但有一些细微差别的类更有用。您可以将这两种方法结合起来。

一个很好的例子是Java类库的集合框架。您有一个接口列表,它定义了列表的行为方式。一些实现例如arraylist和linkedlist。由于它们的行为相似,对两者都起作用的东西在抽象类AbstractList中实现,两者都继承这个。


参见界面基本上是一个"契约"。当您定义接口时,您定义的是一个契约。在扩展抽象类的地方,实现接口。

让我们考虑一个例子。

1
2
3
public interface Friend {
void hello();
}

现在,您已经定义了一个契约,它指出任何想要实现Friend的类都需要为方法hello()提供一个定义。

以下是一个实现:

1
2
3
4
public class myFriend implements Friend {
public void hello()
println("Done");
}

现在myFriend已经履行了合同。现在的问题是:应该在哪里使用接口?

接口帮助您定义必须实现的行为。假设您有一个类A,它定义了一些功能。您希望其他类仅在定义特定行为(方法)时使用此类功能。您在接口方面强制执行此限制。


萨缪尔卡里约似乎很好地回答了这个问题。

除了Java之外,一些框架还需要一个接口来工作。我正在考虑(比如)动态代理,或者一些客户机/服务器代理框架。这是因为它们对对象使用内省来确定由对象实现的接口实现的方法。因此,有时您必须为一个对象实现一个接口,在这个对象中,您通常不会感到麻烦。

注意,接口的原因是特定于Java的。


在构建继承层次结构时使用抽象类。但是,大多数继承层次结构不应该太"深"(即继承层次太多)。许多面向对象的设计书籍会倾向于接口而不是继承(我读过的一本书曾引述一位开发人员的话说,"继承是你不会实现的最酷的[面向对象]功能"),因为这允许类被"契约"分配行为,契约就是接口。

值得注意的是,SamuelCarrijo的答案是——如果您想要一个方法的默认实现,那么您必须使用一个抽象类,该类具有该方法的具体实现,才能给它一个默认实现。可以在子类中重写此默认实现。

希望这有帮助!