抽象类和接口的异同点
- 定义
抽象类:在继承的层次结构中,每个新的子类都使类变得更加明确和具体。如果从一个子类向父类追溯,类就会变得更通用、更加不明确。类的设计应该确保父类包含它的子类的共同特征。有时候,一个父类设计得非常抽象,以至于它都没有任何具体的实例。这样的类称为抽象类。
接口:接口是一种与类相似的结构,用于为对象定义共同的操作。
- 抽象类和接口的异同点
抽象类与接口是Java提供的对现实世界中的实体进行抽象的两种机制,二者具有很大的相似性,同时也具有明显的区别。
比较点 | 抽象类 | 接口 |
关键字 | abstract class | interface |
字段 | 无限制 | 必须是public、static和final |
方法 | 既可以含普通方法,也可以含抽象方法 | 只能含抽象方法,且必须是public的 |
继承/实现 | 只能被类或抽象类继承 | 既可以被接口继承,也能被类或抽象类实现 |
多重继承 | 不支持 | 可以继承多个父接口 |
相同点:1.可以定义抽象方法
2.不能创建本类对象,只能由子类去实例化子类对象
不同点:1.子类要扩展它们时,对抽象类用的是extends关键字(继承),对接口用的是implements(实现)
2.抽象类可以去实现接口,接口只能继承接口,不能继承类
3.一个类可以实现多个接口,但只能继承一个抽象类
4.抽象类可以有构造方法,接口中不能有
- 实例
通常推荐使用接口而非抽象类,因为接口可以为不相关类定义共同的父类型。接口比类更加灵活。考虑Animal类中定义了howToEat方法,如下所示:
Animal 的两个子类定义如下:
假设给定这个继承体系结构,多态使你可以在一个类型为Animal的变量中保存Chicken对象或Duck对象的引用,如下面代码所示:
JVM会基于调用方法时所用的确切对象来动态地决定调用哪个howToEat方法。
可以定义Animal的一个子类。但是,这里有个限制条件。该子类必须是另一种动物(例如,Turkey)。另外一个问题产生了:如果一个动物不可食用,那么它继承Animal类就不合适了。
接口没有这种问题。接口比类拥有更多的灵活性,因为不用使所有东西都属于同一个类型的类。可以在接口中定义howToEat()方法,然后把它当作其他类的共同父类型。例如:
为了定义表示可食用对象的一个类,只须让该类实现Edible接口即可。现在,这个类就成为Edible类型的子类型。任何Edible对象都可以被传递以调用howToEat方法。
- 总结
接口和抽象类都可以用于为对象指定共同的行为。如何决定是采用接口还是类呢?通常,比较强的is-a(是一种)关系清晰地描述了父子关系,应该采用类来建模。例如,因为橘子是一种水果,它们的关系就应该采用类的继承关系来建模。弱的is-a关系,也称为is-kind-of(是一类)关系,表明一个对象拥有某种属性。弱的is-a关系可以使用接口建模。例如,所有的字符串都是可以比较的,因此String类实现了Comparable 接口。圆或者矩形是一个几何对象,因此Circle可以设计为Geometricobject的子类。圆有不同的半径,并且可以基于半径进行比较,因此Circle可以实现Comparable接口。接口比抽象类更加灵活,因为一个子类只能继承一个父类,但是却可以实现任意个数的接口。然而,接口不能包含数据域。Java 8中,接口可以包含默认方法和静态方法,这对简化类的设计非常有用。