设计模式之美(3)-接口

329 阅读5分钟

以下的内容大部分来自极客时间的专栏-设计模式之美。

接口和抽象类是两个经办用到的概念,不仅仅在工作中,面试中也经常被提及。比如“接口和抽象类的区别是什么?什么时候用接口?什么时候用抽象类?抽象类和接口存在的意义是什么?能解决哪些编程问题?”

什么是抽象类和接口,区别在哪里?

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"。应用这条原则,可以将接口和实现相分离,封装不稳定的实现,暴露稳定的接口。上游系统面向接口而非实现编程,不依赖不稳定的实现细节,这样当实现发生变化的时候,上游系统的代码基本上不需要做改动,以此来降低耦合性,提高扩展性。

这条原则的另一个标书方式是:“基于抽象而非实现编程”。

越抽象、越顶层、越脱离具体某一实现的设计,越能提高代码的灵活性,越能应对未来的需求变化。好的代码设计,不仅能应对当下的需求,而且在将来需求发生变化的时候,仍然能够在不破坏原有代码设计的情况下灵活应对。而抽象就是提高代码扩展性、灵活性、可维护性最有效的手段之一。