先看这样一段代码
class Animal(object):
def eat(self, kind):
print("{} eat food....".format(kind))
class Dog(Animal):
pass
class Cat(Animal):
pass
其中,这里面的Dog和Cat都是属于动物,他们有很多类似的属性和动作。这里的抽象基类。
使用场景
第一,抽象基类具备普通继承的功能。因此,在如下两种情况下考虑使用抽象基类:
(1)代码共用。例如上述的代码中,狗、猫、牛、羊这些动物有很多共有的属性和方法,通过实现这个基类,让每个特定的对象继承它,不仅可以实现多态,还可以提高代码的复用能力。
(2)需要获取额外属性。例如在我们的X系统中,下面有若干部件,每个部件都需要按照这样的规范实现特定的方法,就可以发挥抽象基类的限定功能的优势。
例子
开发一个数据中台,对外提供一个接口,让不同组件通过这个接口访问数据库,来读取数据,给这个数据接口的功能包括:
(1)登录数据库;这个功能在不同部件之间可以共用,只需要提供host,user和password即可。
(2)读取数据:每个组件必须单独实现的,可以声明为抽象方法(abstractmethod)。
(3)执行SQL语句:每个子类需要实现的,可以实现抽象的静态方法。
实现过程
第一步:定义抽象基类
Python中有一个模块abc,可以实现抽象基类和抽象方法。
抽象基类:通过继承abc模块的ABC类实现抽象基类;
抽象方法:通过装饰器的方法调用abc模块中的abstractmethod来注解抽象基类的方法。
from abc import ABC
from abc import abstractmethod
class Database(ABC):
def register(self, host, user, password):
print("Host : {}".format(host))
print("User : {}".format(user))
print("Password : {}".format(password))
print("Register Success!")
@abstractmethod
def query(self, *args):
"""
传入查询数据的SQL语句并执行
"""
@staticmethod
@abstractmethod
def execute(sql_string):
"""
执行SQL语句
"""
其中,Database是抽象基类。在这个类下方,有三个方法:
register方法:每个子类都需要的方法,直接实现在抽象基类,是一个普通的类方法;
query方法:在基类进行声明,给出了描述,并没有实现。
execute方法:在基类进行声明,给出了描述,并没有实现。
对于后面两个只有说明,没有实现的部分,它是限定了继承Database的子类必须实现这两个方法。也就是说,谁继承这两个部分,就必须拥有着两个部分。
第二步:具体步骤进行定义
class Component1(Database):
def __init__(self, host, user, password):
self.register(host, user, password)
@staticmethod
def execute(sql_string):
print(sql_string)
def query(self, *args):
sql_string = "SELECT ID FROM db_name"
self.execute(sql_string)
可以看得出,定义了部件1是继承了Database基类,