接口 VS 抽象类
翻译自:http://mindprod.com/jgloss/interfacevsabstract.html
何时使用抽象类,何时使用接口,何时共用呢?接口和抽象类表明上提供了相同的功能,那么我们如何使用它们呢?
何时使用接口?
接口允许使用者从零开始实现接口,或者在其他与改接口目的完全不同的代码中实现该接口,这种情况下,该接口对实现者而言显得次要,因为实现者是为了使用的包而实现接口的。
何时使用抽象类
相反,抽象类提供了更多的实现。它通常提供了默认实现和为全面实现提供辅助。但前提是使用者必须继承抽象类。这对于已存在的具有独立的类继承结构的使用者而言很不方便。Java(c#)中类只能有一个父类。
何时同时使用
你可以同时提供抽象类和接口。实现者可以根据需要忽略抽象类。通过抽象类调用方法略慢于通过接口。
总结
|
接口 |
抽象类 |
多继承 |
支持 |
不支持 |
默认实现 |
不支持 |
可以提供完全实现和待覆盖的桩 |
常量 |
只能提供静态常量,可以在实现者中匿名调用常量,但是这样污染了命名空间。因为常量的声明在使用时是可选的,这样常量的出处很模糊。 |
支持实例变量和静态常量 |
第三方便捷 |
可方便加入第三方代码 |
第三方代码必须重写 |
is-a和can-do |
接口用来描述类的表面行为,而非本身。例如 汽车类实现可回收接口,而改接口被用于很多毫不相干的类。 |
抽象类用于表示类本身。例如定义一个狗类,斑点狗继承狗类表示斑点狗是一种狗,而不仅仅表示具有狗的特性。实现的接口是为了表示类具有某些能力而不是表示类是什么。
|
Plug-in |
你可以使用一个完全不同的接口实现来替换现有实现。但你实现接口时,你完全从零开始没有任何的默认实现。除了少数常量外没有什么来自于结果,通常从其他的工具类获得帮助。这给你足够的只有用于不同的内部设计。 |
你必须使用抽象类的一切作为基础。抽象类的作者为你搭建了框架,框架的好坏依赖于抽象类的作者的水平。 |
同质 |
如果不同的实现只是方法定义相同,最好用接口。 |
如果不同实现是相同的类型,并且有相同的状态和行为,一般使用抽象类。 |
可维护性 |
如果你的客户代码只使用接口交互,你可以使用工厂方法轻松改变类的具体实现 |
与接口相同 |
速度 |
慢,需要在实现类中额外的重定向找到相应的方法。 |
快 |
简洁 |
所有接口的常量都是 public static final,无须定义。你不能通过任何方法提供常量的初始值。接口的所有方法无须声明为abstract。 |
抽象类可以添加共用代码。抽象类可以为实例和静态常量提供初始值。 |
添加新功能 |
当你添加接口的新方法时,你必须修改所有的接口实现类以提供新方法的具体实现。 |
当你添加抽象类的新方法时,你可以提供默认实现,而所有的代码可以不需修改正常工作。 |