抽象类是不能被实例化的类,它用于指定子类必须提供哪些功能,却不实现这些功能。抽象类要有抽象方法,子类实现所有抽象方法后就才能实例化,当然抽象类也可以有非抽象的方法。
抽象类的子类通过继承跟抽象类发生关联,子类通过super()调用抽象类中定义的方法。
python是支持面向对象的编程语言,其实现通过第三方扩展库来实现:abc(Abstract Base Class)模块。Python的抽象基类使用有两种方式:真实子类和虚拟子类。
真实子类
真实子类必须完全实现抽象基类的所有抽象方法。
一个栗子:
import abc
class Animal(metaclass = abc.ABCMeta): ##只能被继承,不能实例化,实例化会报错
@abc.abstractmethod ##加完这个方法子类必须有这个方法,否则报错
def run(self):
pass
@abc.abstractmethod
def eat(self):
pass
class People(Animal):
def run(self):
print("People is walking")
def eat(self):
print("people is eating")
class Pig(Animal):
def run(self):
print("Pig is running")
def eat(self):
print("people is eating")
class Dog(Animal):
def run(self):
print("Dog is zouing")
def eat(self):
print("dog is eating")
peo1 = People()
pig1 = Pig()
dog1 = Dog()
peo1.run()
peo1.eat()
虚拟子类
虚拟子类是将其他的不是从抽象基类派生的类”注册“到抽象基类,让Python解释器将该类作为抽象基类的子类使用,因此称为虚拟子类,这样第三方类不需要直接继承自抽象基类。注册的虚拟子类不论是否实现抽象基类中的抽象内容,Python都认为它是抽象基类的子类,调用 issubclass(子类,抽象基类),isinstance (子类对象,抽象基类)都会返回True。
这种通过注册增加虚拟子类是抽象基类动态性的体现,也是符合Python风格的方式。它允许我们动态地,清晰地改变类的属别关系。当一个类继承自抽象基类时,该类必须完成抽象基类定义的语义;当一个类注册为虚拟子类时,这种限制则不再有约束力,可以由程序开发人员自己约束自己,因此提供了更好的灵活性与扩展性(当然也带来了一些意外的问题)。这种能力在框架程序使用第三方插件时,采用虚拟子类即可以明晰接口,只要第三方插件能够提供框架程序要求的接口,不管其类型是什么,都可以使用抽象基类去调用相关能力,又不会影响框架程序去兼容外部接口的内部实现。
栗子代码
#coding:utf-8
#抽象类虚拟子类
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def getArea():pass #定义获取面积的抽象方法
class House():
def __init__(self,area):self.area=area
def showArea(self):return self.area
Shape.register(House)
issubclass(House,Shape)
house=House(100)
isinstance(house,Shape)
house.getArea()#执行报错,没有该方法
class House():#调整类定义,将showArea方法改成getArea
def __init__(self,area):self.area=area
def getArea(self):return self.area
issubclass(House,Shape)#由于类重新定义,该函数应该返回False
Shape.register(House)#重新注册虚拟子类
house=House(100)#重新定义变量:
issubclass(House,Shape)
isinstance(house,Shape)