以下的内容大部分来自极客时间的专栏-设计模式之美。
接口和抽象类是两个经办用到的概念,不仅仅在工作中,面试中也经常被提及。比如“接口和抽象类的区别是什么?什么时候用接口?什么时候用抽象类?抽象类和接口存在的意义是什么?能解决哪些编程问题?”
什么是抽象类和接口,区别在哪里?
Java中的抽象类,有以下几个特点:
1、抽象类不允许被实例化,只能被继承。也就是说,你不能new一个抽象类的对象
2、抽象类可以包含属性和方法。方法既可以包含代码实现,也可以不包含代码实现。不包含代码实现的方法叫抽象方法。
3、子类继承抽象类,必须实现抽象类中的所有抽象方法。
接口有哪些特性?
1、接口不能包含属性(也就是成员变量)
2、接口只能生命方法,方法不能包含代码实现。
3、类实现接口的时候,必须实现接口中声明的所有方法。
从语法特性上对比,抽象类和接口有比较大的区别。比如抽象类中可以定义属性、方法的实现,而接口中不能定义属性,方法也不能包含代码实现。从设计角度来看,两者也有比较大的区别。
抽象类实际就是类,只不过是一种特殊的类。这种类不能被实例化为对象,只能被子类继承。继承关系是一种is-a的关系,抽象类既然属于类,也表示一种is-a的关系。接口表示一种has-a关系,表示具有某些功能。
抽象类和接口能解决什么编程问题?
为什么需要抽象类?能解决什么问题?
抽象类不能实例化,只能被继承。继承能解决代码复用的问题。所以抽象类也是为代码复用而生的。多个子类可以继承抽象类中定义的属性和方法,避免在子类中,重复编写相同的代码。
为什么需要接口?能解决什么问题?
抽象类更多的是为了代码复用,接口更加侧重于解耦。接口是对行为的一种抽象,相当于一组协议或者契约,也可以叫做契约类。接口实现了约定和实现相分离,可以降低代码间的耦合性,提高代码的可扩展性。
接口是一个比抽象类应用更加广泛,更加重要的知识点。常常提到“基于接口而非实现编程”。
如何决定该用抽象类还是接口?
判断的条件也很简单,如果要表示一种is-a的关系,并且是为了解决代码复用的问题,就用抽象类,如果要表示一种has-a关系,并且是为了解决抽象而非代码复用的问题,就可以使用接口。
面试中如何聊聊接口和抽象类?
如果让我聊聊接口和抽象类,我会这么聊:定义、区别(是什么),存在意义(从哪来),应用(到哪去)。 1、定义: 抽象类:不允许实例化,只能被继承;可包含属性和方法,包含抽象方法;子类继承抽象类必须重写抽象方法。 接口:不允许实例化,只能被实现;不包含属性和普通方法,包含抽象方法、静态方法、default 方法;类实现接口时,必须实现抽象方法。 2、意义: 抽象类:解决复用问题,适用于is-a的关系。 接口:解决抽象问题,适用于has-a的关系。 3、应用: 例如: 解决复用问题:java中的子类FileInputStream和PipeInputStream等继承抽象类InputStream。重写了read(source)方法,InputStream 中还包含其他方法,FileInputStream继承抽象类复用了父类的其他方法。 解决抽象问题:抽象类InputStream实现了Closeable接口,该接口中包含close()抽象方法。Closeable这个接口还在很多其他类中实现了,例如Channel,Socket中都有close() 关闭这个功能,但具体实现每个类又各有不同的实现,这个就是抽象。
“基于接口而非实现编程”
这条原则的英文描述是:"Program to an interface ,not an implementation"。应用这条原则,可以将接口和实现相分离,封装不稳定的实现,暴露稳定的接口。上游系统面向接口而非实现编程,不依赖不稳定的实现细节,这样当实现发生变化的时候,上游系统的代码基本上不需要做改动,以此来降低耦合性,提高扩展性。
这条原则的另一个标书方式是:“基于抽象而非实现编程”。