分清抽象类和接口的区别
简单比较两者的异同点,以求明晰。
一、从语法概念和实际应用上谈二者的区别
抽象类:
abstract修饰的class为抽象类,abstract类不能创建实体对象。
抽象类里方法不必是抽象的,抽象类中定义的抽象方法必须由子类实现,也就是重写。
所以呢,不能有抽象的构造方法或抽象的静态方法。如果子类没有实现抽象父类的所以方法,
那么,子类也必须定义为抽象类。
接口:
接口在一定程度上可以说成是抽象类的特例。
接口中的所有方法都必须是抽象的,接口中的方法定义默认为public abstract。
接口中的变量是全局变量,即public static final修饰的。
简要来说,语法上的区别是:
1.抽象类里可以有构造方法,而接口内不能有构造方法。
2.抽象类中可以有普通成员变量,而接口中不能有普通成员变量。
3.抽象类中可以包含非抽象的普通方法,而接口中所有的方法必须是抽象的。
4.抽象类中的抽象方法的访问类型可以是public,protected和默认类型,但接口中的抽象方法
只能是public类型的,并且默认是public abstract类型的。
5.抽象类中可以有静态方法,但接口中不能有。
6.抽象类和接口中都可以包含静态成员变量,抽象类中静态成员变量的访问类型可以是随意的,
但是接口中的静态成员变量只能是public static的,并且默认是public static的。
7.一个类可以实现多个接口,但只能继承一个抽象类。
二者在应用上的区别:
接口更多的是在系统框架设计方法发挥作用,主要定义模块之间的通信;而抽象类则在代码实现方面发挥作用,实现代码的重用。
二、从实例上简单感受二者的区别
1 /**门的类*/ 2 abstract class Door{ 3 4 abstract void open(){}; 5 6 abstract void close(){}; 7 }
1 /**一个闹铃的接口*/ 2 interface Alarm{ 3 4 void alarm(); 5 6 }
1 /**带有闹铃功能的门的类*/ 2 class AlarmDoor extends Door implements Alarm{ 3 4 void open(){...} 5 6 void close(){...} 7 8 void alarm(){...} 9 10 }
上面这个简单的例子可以直观感受抽象类和接口的用法,同时这样的实现方式也能明确的反映出对问题的正确理解。
其实呢,abstract class表示的是“is a”,interface表示的是"like a"关系,大家在选择时可以作为一个依据,当然这是建立在对问题领域的理解上的,比如:如果我们认为AlarmDoor在概念本质上是报警器,同时又具有 Door的功能,那么上述的定义方式就要反过来了。
abstract class和interface是Java语言中的两种定义抽象类的方式,它们之间有很大的相似性。但是对于它们的选择却又往往反映出对于问题领域中的概 念本质的理解、对于设计意图的反映是否正确、合理,因为它们表现了概念间的不同的关系(虽然都能够实现需求的功能)。这其实也是语言的一种的惯用法。
总结几句话来说:
1、抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象。
2、抽象类要被子类继承,接口要被类实现。
3、接口只能做方法申明,抽象类中可以做方法申明,也可以做方法实现
4、接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。
5、抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是抽象类。同样,一个实现接口的时候,如不能全部实现接口方法,那么该类也只能为抽象类。
6、抽象方法只能申明,不能实现。abstract void abc();不能写成abstract void abc(){}。
7、抽象类里可以没有抽象方法
8、如果一个类里有抽象方法,那么这个类只能是抽象类
9、抽象方法要被实现,所以不能是静态的,也不能是私有的。
10、接口可继承接口,并可多继承接口,但类只能单根继承。
特别是对于公用的实现代码,抽象类有它的优点。抽象类能够保证实现的层次关系,避免代码重复。然而,即使在使用抽 象类的场合,也不要忽视通过接口定义行为模型的原则。从实践的角度来看,如果依赖于抽象类来定义行为,往往导致过于复杂的继承关系,而通过接口定义行为能 够更有效地分离行为与实现,为代码的维护和修改带来方便。