首页 > Python笔记 阅读数:21

Python类的继承详解

俗话说,“虎父无犬子”,“龙生龙,凤生凤,老鼠的儿子会打洞”,这在一定程度上说明了继承的重要性—优秀的特性要留给后辈。

在面向对象程序设计中,继承(Inheritance)是软件复用的关键技术。通过继承,子类可以复用父类的优秀特性,同时还可进一步扩充新的特性,适应新的需求。

在已有类的基础上新增自己的特性,继而产生新类的过程,称为生。我们把既有的类称为基类(Base Class)、超类(Super Class)或者父类(Parent Class),而将派生出的新类称为派生类(Derived Class)或子类(Subclass)。

如前所述,继承的目的在于实现代码重用,即对于已有的、成熟的功能,令子类从父类处奉行“拿来主义”。而派生的目的则在于,当新的问题出现且原有代码无法解决(或不能完全解决)时,需要对原有代码进行全部(或部分)改造。

对于面向对象的程序而言,设计孤立的类是比较容易的,难的是正确设计好类的层次结构以达到代码高效重用的目的。Python 不仅支持类的继承,且如 C++ 一样,它还支持多继承,多继承存在“菱形继承”的风险。

Python派生类的定义格式如下:

class 派生类名 (基类名1 [,基类名2…,]):
    <语句-1>
    ……
    <语句-N>


这里需要注意的是,圆括号中基类的顺序是有讲究的。若基类中有相同的方法名,而在子类使用时未指定,则Python将从基类列表中以从左到右的顺序查找是否包含该方法。

通常,基类必须与派生类定义在同一个作用域(模块)内。如果基类定义在另一个模块中,则要指定模块类名,如下所示:

class 派生类名 (模块名.基类名):
    <语句-1>
    ……
    <语句-N>


下面我们演示一些 Python 中的单一继承操作,如例 2 所示。

【例 2】Python 中的单一继承操作(class-people-student.py)
class Person:
    height = 140 #定义类的数据成员
    #定义构造方法
    def __init__(self,name,age,weight):
        self.name = name #定义对象的数据成员属性
        self.age = age
        #定义私有属性,私有属性在类外部无法直接访问
        self.__weight = weight
    def speak(self):
        print ("%s 说:我 %d 岁, 我体重为 %d kg, 身高为 %d cm" %(self.name, self.age, self.__weight, Person.height))

#单一继承示范
class Student(Person):
    grad =' '
    def __init__(self, name, age, weight, grad):
        #调用父类的构造方法,初始化父辈数据成员
        Person.__init__(self, name,age,weight)
        self.grade = grad

    #覆写父类的同名方法
    def speak(self):
        print ("%s 说:我 %d 岁了,我在读 %d年级"%(self.name, self.age, self.grade))

stu = Student('Alice', 11, 40, 5)
stu.speak()
程序执行结果为:

Alice 说:我 11 岁了,我在读 5年级


如代码第 13 行所示,子类 Student 继承自父类 Person,也就是说,父类的数据成员和方法成员,子类 Student 全盘接收。但是,这两个类彼此之间毕竟还是有“代沟”的。比如,__init__(self, name, age, weight, grad) 是构造方法(第 15~18 行),它用于初始化全部数据成员,但对于来自父类的数据成员(如 name、age 和__weight),它们的初始化还得交由父类自己的构造方法来完成(第 17 行)。而 Student 类自己新建的数据成员 grade 则需要由它自己进行初始化(第 18 行)。

类似地,如果想在子类中调用父类的方法,可使用内置方法 super( ) 或通过“父类名.方法名”的方式来实现,如第 17 行的 Person.__init__()。

此外,Student 类还继承了来自父类 Student 的公有方法 speak( )。但如果父类方法的功能不能满足子类的需求,那么可在子类中重写父类的方法,这种改造父类同名方法的策略,称为覆写(Override)。代码的第 21~22 行就是一个对父类方法 speak( ) 进行的覆写操作。

相关文章