如果把类视为现实对象的抽象,那么抽象类可视为类的一种特殊抽象:指定了其子类必须实现的方法。具体来说:抽象类本身无法实例化,只能被继承,其职责是规定子类应实现的一组抽象方法,即子类必须实现这些抽象方法。
抽象类的使用具有如下优点:(1)提供了一种类似接口类的功能;(2)可统一子类的抽象方法,实现功能的归一化,从而规范代码;(3)处理继承问题方面更加规范、系统,明确调用之间的相互关系,使得继承层次更加清晰。
单从规定子类应实现的一组抽象方法而言,下面给出一种近似而粗糙的解决方案:
class Animal(object):
def eat(self):
raise NotImplementedError
class Dog(Animal):
pass
if __name__ == '__main__':
dog = Dog()
dog.eat() # NotImplementedError
通过在父类相应函数中主动抛出NotImplementedError
的方式,可以在一定程度上约束子类。但这种约束是被动的,相较于抽象类,抽象类本省可以实例化;同时在不主动调用该方法时,也不会报错。
Python中一般通过调用内置库collections.abc
和abc
来实现抽象类的功能。
其中collections.abc
定义了一系列具体的抽象类,典型的包括:
Container:提供抽象方法__contains__
Callable:提供抽象方法__call__
Sized: 提供抽象方法__len__
而abc
则提供了更顶层的抽象类方案,可方便实现定制化抽象方法功能:
from abc import ABCMeta, abstractmethod
class Animal(metaclass=ABCMeta):
@staticmethod
@abstractmethod
def favorite(self): # 抽象静态方法
"""favorite meat"""
@abstractmethod
def eat(self): # 抽象方法
"""the eat funciton subclass must implement!"""
# 子类继承必须实现抽象方法
class Dog(Animal):
def eat(self, food):
print("The dog is eating {}".format(food))
def favorite(self, food):
print("The dog's favorite food is {}".format(food))
return food
if __name__ == '__main__':
# 无法直接实例化
# animal = Animal() # TypeError: Can't instantiate abstract class Animal with abstract methods eat, favorite
dog = Dog()
dog.eat('meat') # The dog is eating meat
dog.favorite('pork') # The dog's favorite food is pork