抽象类和接口是两个经常被用到的语法概念,是面向对象四大特性,以 及很多设计模式、设计思想、设计原则编程实现的基础.

举例:

  1. 我们可以使用接口来实现面 向对象的抽象特性
  2. 多态特性和基于接口而非实现的设计原则
  3. 使用抽象类来实现面向对象 的继承特性和模板设计模式等等

不支持接口和抽象类概念的有

C++ 这种编程语言 只支持抽象类,不支持接口;而像 Python 这样的动态编程语言,既不支持抽象类,也不支 持接口。

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

1 抽象类

抽象类不允许被实例化,只能被继承 也就是说,你不能 new 一个抽象类的对象出来 抽象类可以包含属性和方法。方法既可以包含代码实现(比如 Logger 中的 log() 方 法),也可以不包含代码实现(比如 Logger 中的 doLog() 方法)。不包含代码实现的 方法叫作抽象方法

  1. // 抽象类
  2. public abstract class Logger {
  3. private String name;
  4. private boolean enabled;
  5. private Level minPermittedLevel;
  6. public Logger(String name, boolean enabled, Level minPermittedLevel) {
  7. this.name = name;
  8. this.enabled = enabled;
  9. this.minPermittedLevel = minPermittedLevel;
  10. }
  11. public void log(Level level, String message) {
  12. boolean loggable = enabled && (minPermittedLevel.intValue() <= level.intVal
  13. if (!loggable) return;
  14. doLog(level, message);
  15. }
  16. protected abstract void doLog(Level level, String message);
  17. }
  18. // 抽象类的子类:输出日志到文件
  19. public class FileLogger extends Logger {
  20. private Writer fileWriter;
  21. public FileLogger(String name, boolean enabled,
  22. Level minPermittedLevel, String filepath) {
  23. super(name, enabled, minPermittedLevel);
  24. this.fileWriter = new FileWriter(filepath);
  25. }
  26. @Override
  27. public void doLog(Level level, String mesage) {
  28. // 格式化 level 和 message, 输出到日志文件
  29. fileWriter.write(...);
  30. }
  31. }
  32. // 抽象类的子类: 输出日志到消息中间件 (比如 kafka)
  33. public class MessageQueueLogger extends Logger {
  34. private MessageQueueClient msgQueueClient;
  35. public MessageQueueLogger(String name, boolean enabled,
  36. Level minPermittedLevel, MessageQueueClient msgQueueClient) {
  37. super(name, enabled, minPermittedLevel);
  38. this.msgQueueClient = msgQueueClient;
  39. }
  40. @Override
  41. protected void doLog(Level level, String mesage) {
  42. // 格式化 level 和 message, 输出到消息中间件
  43. msgQueueClient.send(...);
  44. }
  45. }

2 接口

  1. 接口不能包含属性(也就是成员变量)。
  2. 接口只能声明方法,方法不能包含代码实现。
  3. 类实现接口的时候,必须实现接口中声明的所有方法

    3 接口与抽象类区别

    如抽象类中可以定义属性、方法的实现,而接口中不能定义属性,方法也不 能包含代码实现等
    抽象类实际上就是类,只不过是一种特殊的类,这种类不能被实例化为对象,只能被子类继 承。我们知道,继承关系是一种 is-a 的关系
    接口表示一种 has-a 关系,表示具有某些功能。对于 接口,有一个更加形象的叫法,那就是协议(contract)。

8.2、 抽象类和接口能解决什么编程问题?

1、 为什么需要抽象类?它能够解决什么编程问题?

继承能解 决代码复用的问题。所以,抽象类也是为代码复用而生的,多个子类可以继承抽象类中定义 的属性和方法,避免在子类中,重复编写相同的代码。
并且可以利用多态特性实现功能的拓展。

2、 为什么需要接口?它能够解决什么编程问题?

接口就更侧重于解耦, 接口是对行为的一种抽象,相当于 一组协议或者契约, 调用者只需要关注抽象的接口,不需 要了解具体的实现 , 具体的实现代码对调用者透明。接口实现了约定和实现相分离,可以降 低代码间的耦合性,提高代码的可扩展性
接口是一个比抽象类应用更加广泛、更加重要的知识点。比如,我们经常提到 的“基于接口而非实现编程”

8.3、 如何模拟抽象类和接口两个语法概念?

Java 的接口语法实现了一个 Filter 过滤器

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

判断的标准很简单。如果我们要表示一种 is-a 的关系,并且是为了解决代码复用 的问题,我们就用抽象类
如果我们要表示一种 has-a 关系,并且是为了解决抽象而非代 码复用的问题,那我们就可以使用接