如果你只学习过 Python,那么看到“接口类和抽象类”这几个字眼肯定是一脸疑惑,甚至感觉一点概念都没有,原因在于 Python 原生语法是不支持抽象类与接口类的,并且很多教程上也很少提及这两个概念。对于其他语言,C++ 只支持抽象类,Java 支持接口和抽象类,Go 只支持接口。如果我们想要在 Python 中实现接口类和抽象类,可以借助abc库来完成,也可以自己实现。

1. 定义

接口类定义
- 不支持实例化
- 仅包含抽象方法而不包含属性
- 实现接口类的类必须实现其所有方法
- 接口类标识一种 has-a 的关系,即拥有某种行为的概念
抽象类定义
- 不支持实例化,
- 可以包含抽象方法、普通方法和属性
- 子类继承抽象类的属性和方法,且子类必须重写抽象类的所有抽象方法
- 抽象类标识一种 is-a 的关系,即属于某种东西的概念

如果看了这些描述,对这两个概念还不是很清晰,建议看下 JAVA 中 📌抽象类与接口

2. 实现接口类和抽象类

| ```python from abc import ABCMeta, abstractmethod

class BaseAnimal(metaclass=ABCMeta): color = None

  1. @abstractmethod
  2. def eat(self):
  3. pass

class Tigger(BaseAnimal): def eat(self): pass

  1. | ```python
  2. from abc import ABCMeta, abstractmethod
  3. from AbstractClass import BaseAnimal
  4. class Flyable(metaclass=ABCMeta):
  5. @abstractmethod
  6. def fly(self):
  7. pass
  8. class Bird(BaseAnimal, Flyable):
  9. def eat(self):
  10. pass
  11. def fly(self):
  12. pass

| | —- | —- |

不同于 Java,Python 中所实现的接口类和抽象类除了概念上不一样外,形式上是完全一样的。作为 Python 开发者,如果在设计时引入抽象类和接口类,最好的方式是通过名称去区分。

这里我们参考阿里巴巴 JAVA 开发手册对于抽象类和接口类的命名规范,抽象类命名采用Abstract或者Base作为前缀,接口类采用Impl或者able作为后缀

3. 注意点

因为 JAVA 中所有类都是单继承的,所以抽象类完美地解决了单继承需求中的规范问题。对于多继承的需求,由于 JAVA 本身语法不支持,所以接口很好地解决了多继承的问题。

由于 Python 本身就是多继承的,在继承抽象类的过程中,我们应该尽量避免多继承。在继承接口的时候,我们应该多继承接口。

4. 参考文档