Python进阶-08-继承性
来源:《Python从小白到大牛》关东升
1、继承性
类的继承是面向对象语言的基本特征,多态性的前提是继承性。
1.1继承概念
为了了解继承性,先看这样一个场景:一位面向对象的程序员小赵,在编程过程中需要描述和处理个人信息,于是定义了类Person,如下所示:
class Person:
def __init__(self,name,age):
self.name=name # 名字
self.age=age # 年龄
def info(self):
template='Person [name={0},age={1}]'
s=template.format(self.name,self.age)
return s
一周以后,小赵又遇到了新的需求,需要描述和处理学生信息,于是他又定义了一个新的类Student,如下所示:
class Student:
def __init__(self,name,age,school):
self.name=name # 名字
self.age=age # 年龄
self.school=school # 所在学校
def info(self):
template='Student [name={0},age={1},school={2}]'
s=template.format(self.name,self.age,self.school)
return s
很多人会认为小赵的做法能够被理解并认为这是可行的,但问题在于Student和Person两个类的结构太接近了,后者之比前者多了一个school实例变量,却要重复定义其他所有的内容,实在让人“不甘心”。Python提供了解决类似问题的机制,那就是类的继承,代码如下所示:
class Student(Person):
def __init__(self,name,age,school):
super().__init__(name,age)
self.school=school # 所在学校
上述代码第一行声明了Student类继承Person类,其中小括号中的是父类,如果没有指明父类(一对空的小括号或省略小括号),则默认父object,objcet类是Python的根类。
上述代码第二行定义构造方法,子类中定义构造方法时首先要调用父类的构造方法,初始化父类实例变量。第三行代码时调用父类的构造方法,super()函数是返回父类引用,通过它可以调用父类中的实例变量和方法。第四行是定义school实例变量。
提示:子类继承父类时只是继承父类中公有的成员变量和方法,不能继承私有的成员变量和方法。
1.2重写方法
如果子类方法名与父类方法名相同,而且参数列表也相同,只是方法体不同,那么子类重写(Override)了类的方法。
class Animal(object):
"""定义动物类"""
def __init__(self,name,age,sex=1,weight=0.0):
self.age=age
self.sex=sex
self.weight=weight
def eat(self):
self.weight+=0.05
print('动物吃...')
class Dog(Animal):
def eat(self):
self.weight+=0.1
print('狗狗吃...')
a1=Dog(2,0,10.0)
a1.eat() # 狗狗吃...
上述代码定义了一个eat()方法,子类继承父类并重写了eat()方法。那么通过子类实例调用eat()方法时,会调用子类重写的eat()。
1.3多继承
所谓多继承,就是一个子类有一个多个父类。大部分计算语言如Java、Swift等,只支持单继承,不支持多继承。主要是多继承会发生方法冲突。例如,客轮是轮船也是交通工具,客轮的父类是轮船和交通工具。主要是多继承会发生方法冲突。
例如,客轮是轮船也是交通工具,客轮的父类是轮船和交通工具,如果两个父类都定义了run()方法,子类客轮继承哪一个run()方法呢?
Python支持多继承,但Python给出了解决方法名字冲突的方案。这个方案是,当子类实例调用一个方法时,先从子类中查找,如果没有找到则查找父类。父类的查找顺序是按照子类声明的父类列表从左到右查找,如果没有找到再找父类的父类,依次查找下去。
多继承实例代码如下:
class ParentClass1:
def run(self):
print('ParentClass1 run...')
class ParentClass2:
def run(self):
print('ParentClass2 run...')
class SubClass1(ParentClass1,ParentClass2):
pass
class SubClass2(ParentClass2,ParentClass1):
pass
class SubClass3(ParentClass1,ParentClass2):
def run(self):
print('SubClass3 run...')
sub1=SubClass1()
sub1.run() # ParentClass1 run...
sub2=SubClass2()
sub2.run() # ParentClass2 run...
sub3=SubClass3()
sub3.run() # SubClass3 run...