What
python中定义可以定义抽象类,和Java中的抽象类是一样的,不能被直接实例化,而是作为一个基类,主要用于定义一组接口规范,接口的实现在继承其的子类中完成,并且要求子类必须实现定义的所有接口,和Java一样如何子类未完全实现父类中的所有接口,那么这个子类也会被定义成为一个抽象类,不能直接实例化。
Why
- 强制接口一致性
- 实现多态性
- 促进代码重用
- 模板化编程
总之就是好处多多
How
定义抽象类主要有两种方法一种是通过继承ABC类,另一种是直接使用ABCMeta作为元类。
还可以结合使用 @abstractmethod 和 @abstractproperty(Python 3.3 及以上版本推荐使用 @property + @abstractmethod)来定义抽象方法和属性。
下面将依次介绍这两种方法。
继承ABC类
最常用、最简洁的方式,适用于绝大多数情况。只需要让自己的抽象类去继承abc.ABC即可,并使用@abstractmethod装饰器标记应该被子类实现的方法。
python">from abc import ABC, abstractmethod
class MyabstractClass(ABC):@abstractmethoddef my_method(self):pass@property@abstractmethoddef my_property(self):pass
使用ABCMeta元类
python">from abc import ABCMeta, abstractmethodclass MyAbstractClass(metaclass=ABCMeta):@abstractmethoddef my_method(self):pass@property@abstractmethoddef my_property(self):pass
- @abstractmethod:用于装饰普通方法,表明该方法是抽象的,所有非抽象子类都必须实现它。
- @property + @abstractmethod:用于定义抽象属性,确保子类提供具体的属性实现。
静态方法和类方法
除了普通的实例方法外,也可以定义抽象的静态方法和类方法。通过组合@abstractmethod 和 @staticmethod 或 @classmethod 来完成。
python">from abc import ABC, abstractmethodclass AbstractBaseClass(ABC):@abstractmethod@staticmethoddef static_method():"""这是一个抽象静态方法"""pass@abstractmethod@classmethoddef class_method(cls):"""这是一个抽象类方法"""pass
注册虚拟子类
有时可能想要声明某个类实现了特定接口,但并不直接继承自那个抽象基类。这时可以使用 register() 方法来注册一个“虚拟子类”。
python">from abc import ABC, abstractmethodclass PluginBase(ABC):@abstractmethoddef load(self, input):passclass LocalPlugin:def load(self, input):return input.read()PluginBase.register(LocalPlugin) # 注册 LocalPlugin 为 PluginBase 的虚拟子类# 测试是否成功注册
print(issubclass(LocalPlugin, PluginBase)) # 应该输出 True
local_plugin = LocalPlugin()
print(isinstance(local_plugin, PluginBase)) # 应该输出 True