如果你只学习过 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
@abstractmethod
def eat(self):
pass
class Tigger(BaseAnimal): def eat(self): pass
| ```python
from abc import ABCMeta, abstractmethod
from AbstractClass import BaseAnimal
class Flyable(metaclass=ABCMeta):
@abstractmethod
def fly(self):
pass
class Bird(BaseAnimal, Flyable):
def eat(self):
pass
def fly(self):
pass
| | —- | —- |
不同于 Java,Python 中所实现的接口类和抽象类除了概念上不一样外,形式上是完全一样的。作为 Python 开发者,如果在设计时引入抽象类和接口类,最好的方式是通过名称去区分。
这里我们参考阿里巴巴 JAVA 开发手册对于抽象类和接口类的命名规范,抽象类命名采用Abstract
或者Base
作为前缀,接口类采用Impl
或者able
作为后缀
3. 注意点
因为 JAVA 中所有类都是单继承的,所以抽象类完美地解决了单继承需求中的规范问题。对于多继承的需求,由于 JAVA 本身语法不支持,所以接口很好地解决了多继承的问题。
由于 Python 本身就是多继承的,在继承抽象类的过程中,我们应该尽量避免多继承。在继承接口的时候,我们应该多继承接口。