类的继承

在某种情况下,一个类会有子类(或称派生类)。子类比原本的类(称为父类基类)要更加具体化。例如,Student 这个类可能会有它的子类 MiddleSchoolStudentCollegeStudent 。子类会继承父类的属性(变量和方法),并且也可包含它们自己的。我们假设 Dog 这个类有一个方法叫做 bark() 和一个属性叫做 color。它的子类(如 ChineseRuralDogGermanShepherdDog)会继承这些成员。这意味着只需要将相同的代码写一次。

这种子类具有父类的属性和方法的机制,称为继承(Inheritance)。

继承可避免相同代码的重复书写,减少代码的数量。继承是面向对象编程的三大基本特征之二。

定义子类#

子类定义的语法如下:

class DerivedClassName(BaseClassName):
    ...

即需要将父类 BaseClassName 列在子类 DerivedClassName 头部的括号内。

在使用子类及其实例化对象时,如果引用了其属性,并且在子类中找不到此属性,会转往基类中查找此属性,如果基类也继承自其它某个类,此搜索将被递归地应用。

示例:

class Dog:
    def __init__(self):
        self.name = None
        self.breed = None
        self.bark_mode = '汪…汪…'
    def bark(self):
        print(f'一只名为{self.name}的{self.breed}在{self.bark_mode}地叫着。')

class ChineseRuralDog(Dog): pass
my_dog = ChineseRuralDog()
my_dog.name = '大黄'
my_dog.breed = '中华田园犬'
my_dog.bark()  # 一只名为大黄的中华田园犬在汪…汪…地叫着。

以下示例无法运行,请分析原因:

class Dog:
    def __init__(self):
        self.name = None
        self.breed = None
        self.bark_mode = '汪…汪…'
    def bark(self):
        print(f'一只名为{self.name}的{self.breed}在{self.bark_mode}地叫着。')
class ChineseRuralDog(Dog):
    def __init__(self):
        self.breed = '中华田园犬'
my_dog = ChineseRuralDog()
my_dog.name = '大黄'
my_dog.bark()  # AttributeError: 'ChineseRuralDog' object has no attribute 'bark_mode'

又一个示例:

class Shape:
    def draw(self): ...
    def edge_length(self): ...

class Polygon(Shape):
    def area(self): ...

class Rectangle(Polygon):
    def width(self): ...
    def height(self): ...

rect = Rectangle()
rect.draw()
rect.area()
rect.width()

多重继承#

一个子类可以有多个父类,此种继承关系称为多重继承。如下所示:

class DerivedClassName(Base1, Base2, Base3):
    ...

在搜索从父类所继承的属性属性时,会按照深度优先、从左至右的顺序进行,当层次结构中存在重叠时不会在同一个类中搜索两次。因此,如果某一属性在 DerivedClassName 中未找到,则会到 Base1 中搜索它,然后(递归地)到 Base1 的基类中搜索,如果还未找到,再到 Base2 中搜索,依此类推。

示例:

class HeadingMachine:
    """掘进机"""
    def driving(self): ...

class RockDrill:
    """凿岩机"""
    def drill(self): ...

class BolterMiner(HeadingMachine, RockDrill):
    """掘锚机"""
    def other(self): ...

另一个示例:

class Reader:
    def read(self): ...

class Writer:
    def write(self): ...

class File(Reader, Writer):
    def other(self): ...

检查继承关系#

Python 有两个内置函数可被用于继承机制:

  • isinstance()检查一个实例的类型,isinstance(obj, int) 仅会在 obj.__class__int 或某个派生自 int 的类时为 True
  • issubclass()检查类的继承关系,issubclass(bool, int)True,因为 boolint 的子类。 但是,issubclass(float, int)False,因为 float 不是 int 的子类。
类的定义和使用方法重写