接口 vs 抽象类
我被询问过很多次的一个问题就是Java接口和抽象类之间的区别,以及何时使用它们。我已经多次通过电子邮件回答了这个问题,所以我决定编写本篇教程。
Java接口用于将某些组件的接口与实现分离。换句话说,接口可以将其实现类与接口独立开来。因此,你可以交换接口的实现,而无需使用接口更改类。
抽象类通常被用作子类扩展的基类。在一些编程语言使用抽象类来实现多态,并将接口与实现分开,但在Java中使用接口来完成这一目标。请记住,一个Java类只能有一个超类,但它可以实现多个接口。因此,如果一个类已经有了不同的超类,它可以实现一个接口,但是它不能扩展另一个抽象类。因此,接口是暴露公共接口的更灵活的机制。
如果你需要将接口与其实现分离,请使用接口。如果还需要提供接口的基类或默认实现,请添加实现该接口的抽象类(或普通类)。
下面是一个示例,显示引用接口的类,实现该接口的抽象类和扩展抽象类的子类。
蓝色的类仅仅知道接口。抽象类实现接口,同时子类继承了抽象类
下面是抽象类中的代码示例,但添加了一个由抽象基类实现的接口。这样做之后它就像上面的图表。
首先是接口:
public interface URLProcessor {
public void process(URL url) throws IOException;
}
然后是抽象基类:
public abstract class URLProcessorBase implements URLProcessor {
public void process(URL url) throws IOException {
URLConnection urlConnection = url.openConnection();
InputStream input = urlConnection.getInputStream();
try{
processURLData(input);
} finally {
input.close();
}
}
protected abstract void processURLData(InputStream input)
throws IOException;
}
然后继承自抽象类的子类:
public class URLProcessorImpl extends URLProcessorBase {
@Override
protected void processURLData(InputStream input) throws IOException {
int data = input.read();
while(data != -1){
System.out.println((char) data);
data = input.read();
}
}
}
最后,使用接口URLProcessor作为变量类型,即使它是子类UrlProcessorImpl的实例。
URLProcessor urlProcessor = new URLProcessorImpl();
urlProcessor.process(new URL("http://jenkov.com"));
使用接口和抽象基类可以让你的代码更加灵活。通过继承抽象基类就可以实现简单的URL处理器。如果你需要更高级的东西,你的URL处理器可以直接实现URLProcessor接口,而不是从URLProcessorBase继承。
下一篇:枚举