接口和抽象类

刚开始,接触C#语言的时候,不太能分清接口Interface和抽象类Abstract Class的区别,Java语言也有一样的疑问。

很容易说出它们在语法上的区别:

  1. 一个类可以实现多个接口,但是只能继承自一个抽象类;
  2. 接口只有定义没有实现,抽象类中可以有具体实现(只要有一个抽象函数即为抽象类)。

那么语义上看,要怎么区分二者呢?接口主要是表示能力,这个能力是用几个方法来表示的(很多时候只要有一个方法就行),比如这个类可以做相等关系的比较,这个类可以被克隆等等。而抽象类往往表达的是更复杂的概念,抽象类代表了一类事物,它们有很多种类,这些种类间有很多的共性,形成了抽象类,就像没有具体的马,只有白马黑马,抽象类中往往有一些功能的实现,它们有点类似函数式语言中的high-order function,主要是调度其他的抽象的函数来完成功能,在设计模式的术语中,叫做模板方法,反过来看,抽象类大部分的应用场景其实都是模板方法。

其实像C++语言支持多继承,那么一个全是抽象函数的类的作用就跟接口是一样的,因此在C++语言中,就没有类似C#或Java中的接口的语法结构。一般来说,如果一门语言不支持多继承,又要表达类似接口的概念,才会出现接口的语法结构,反过来说,当一门语言支持多继承时,我们可以自己规定某些类必须全部是抽象函数(纯虚函数),从而实现接口的功能。

总的启示是,要根据问题的需要寻找语言特性来编程,而语言特性不一定在你使用的语言中不一定会有直接的语法结构支持,但是往往都能有变通的办法。