设计模式之美--抽象类与接口

面向对象编程中,抽象类和接口是两个经常被用到的语法概念。我们经常在工作中用到,也会在面试中被提及。比如两者的区别在哪里?今天就来理一理这两者的关系。

抽象类

抽象目的是复用,有三个特性。

  1. 抽象类不允许被实例化,只能被继承。
  2. 抽象类可以包含属性和方法。方法可以包含代码实现,也可以不包含。
  3. 子类继承抽象类,必须实现抽象类中的 所有 抽象方法。

继承关系是一种 is-a 关系。为了解决代码复用问题。

抽象类解决了什么问题

如果没有抽象类,作为普通的父类的情况下,当我们写好父类的方法后,由于不是抽象类,则编译器不会强制要求子类重写该方法,我们有可能会忘记重新实现该方法。另一方面,父类可以被实例化,这也增加了类被误调用的风险,虽然可以通过设置私有的构造函数的方式来解决(比如单例模式),但是不够优雅。

接口

接口目的是拓展,也有三个特性。

  1. 接口不能包含属性。
  2. 接口只能声明方法,方法不能包含代码实现。
  3. 类实现接口的时候,必须实现接口中声明的 所有 方法。

接口表示 has-a 关系,表示具有某些功能。对于接口,有个更加形象的叫法,就是协议,表示一种规范。

接口解决了什么问题

接口侧重于解耦。接口是对行为的一种抽象,相当于一组协议或者契约。你可以联想类比一下API接口。调用者只需要关注抽象的接口,不需要了解具体的实现。接口实现了约定和实现相分离,可以降低代码间的耦合性,提高代码的可拓展性。

如何决定该用抽象类还是接口?

根据我们想要表示的关系来进行判断。另外,从类的继承层册来看,抽象是一种自下而上的设计思路,现有子类的代码重复,然后在有上层的父类抽象。而接口正好相反,他是一种自上而下的设计思路。我们在编程的时候,一般都是先设计接口,然后考虑其具体实现。