面向对象三大特性之继承
继承:
继承是一种关系,是什么是什么的关系。通过继承,一个对象可以直接使用另一个对象内的内容。
例如:王思聪继承王健林,那么王思聪就可以拥有王健林的财产。
被继承的一方称为父类,继承的那一方称为子类
2.为什么用继承
为了减少代码的重复,可以让代码具有复用性
3.语法
就是在类名后面的括号中指定要继承的父类。
class A:
pass
class B(A):
pass
例子:
class Teacher: def __init__(self,name,gender,age): self.name = name self.gender = gender self.age = age def say_hi(self): print("hi my name is %s age is %s gender is %s" % (self.name,self.age,self.gender)) class Student: def __init__(self,name,gender,age): self.name = name self.gender = gender self.age = age def say_hi(self): print("hi my name is %s age is %s gender is %s" % (self.name,self.age,self.gender)) #创建两个对象 t1 = Teacher("Jack","man",20) t1.say_hi() s1 = Student("Maria","woman",20) s1.say_hi()
4.先抽象在继承
问题:继承描述的是子类与父类的关系,比如我学生类,继承了老师类,那么学生类就拥有了老师类里面的内容,但老师类里面可能有方法教课,这个显然不是学生类应该具备的,这个时候就要用到抽象,就是把2个类中完全共同的部分抽出来,然后再继承抽出来的那个类。
所以要先抽象再继承
例子
# 抽取老师和学生的相同内容 形成一个新的类,作为它们的公共父类 class Person: def __init__(self,name,gender,age): self.name = name self.gender = gender self.age = age def say_hi(self): print("hi my name is %s age is %s gender is %s" % (self.name,self.age,self.gender)) class Teacher(Person): #指定Teacher类继承Person类 pass class Student(Person): #指定Student类继承Person类 pass #创建两个对象 t1 = Teacher("Jack","man",20) t1.say_hi() s1 = Student("Maria","woman",20) s1.say_hi()
抽象最主要的作用就是划分类别,降低复杂度,也就是每个类干自己的事,每个类相同的事交给父类做。
6.派生
就是说子类拥有父类中没有的属性和方法那么就是派生
例子:
# 抽取老师和学生的相同内容 形成一个新的类,作为它们的公共父类 class Person: def __init__(self,name,gender,age): self.name = name self.gender = gender self.age = age def say_hi(self): print("my name is %s age is %s gender is %s" % (self.name,self.age,self.gender)) class Teacher(Person): def show(self): print('教书')
7.覆盖
就是说子类拥有父类中相同的属性和方法,按照类属性的查找顺序,会查自己的,那么这个时候就是可以说是覆盖
例子:
class Person: def __init__(self,name,gender,age): self.name = name self.gender = gender self.age = age def say_hi(self): print("my name is %s age is %s gender is %s" % (self.name,self.age,self.gender)) class Teacher(Person): #指定Teacher类继承Person类 # Teacher类从Person类中继承到了say_hi方法 但是,老师打招呼时应当说出自己的职业是老师,所以需要 # 定义自己的不同的实现方式 def say_hi(self): print("hi i am a Teacher") #print("my name is %s age is %s gender is %s" % (self.name,self.age,self.gender)) #上一行代码与父类中完全相同,可以直接调用父类提供的方法 Person.say_hi(self) # 创建Teacher对象 t1 = Teacher("Jack","man",20) t1.say_hi()
8.子类访问父类的属性或方法 super ().名字
如果你继承一个已有的类,并且你覆盖了init 一定要先调用父类的init
例子:
class Vehicle: #定义交通工具类 Country='China' def __init__(self,name,speed,load,power): self.name=name self.speed=speed self.load=load self.power=power def run(self): print('开动啦...') class Subway(Vehicle): #地铁 def __init__(self,name,speed,load,power,line): #super(Subway,self) 就相当于实例本身 在python3中super()等同于super(Subway,self) super().__init__(name,speed,load,power) self.line=line def run(self): print('地铁%s号线欢迎您' %self.line) super(Subway,self).run() class Mobike(Vehicle):#摩拜单车 pass line13=Subway('中国地铁','180m/s','1000人/箱','电',13) line13.run()
9.继承的原理
对于定义的每一个类,python通过一个算法算出一个查找顺序放在一个mro列表中,这个mro
列表就是一个简单的所有基类的线性顺序表。所以说类的查找顺序都是按照这个mro列表来查询的。
就是用类名点mro
10,新式类与经典类
新式类就是显式或隐式的继承了object的类
经典类就是没有继承object的类。
在python3中都是直接或间接继承了object的新式类
经典类仅在python2中有
所以为了代码的通用性,最好在类名后面继承一下object
11.菱形继承 了解
就是一个类继承了多个类,多个类又有一个公共的父类。
查找顺序就是按照mro列表查询的,新式类是先广度在深度,就是最后找公有的父类
经典类是先深度再广度,就是一路走到底再换另一条路走
12,属性的查找顺序
属性的查找顺序是先查找对象自身的,没有再查找所在的类的,再没有就查找父类,再找父类的父类,最后找到object,如果object还没有那就直接崩盘。
子类中访问父类的内容:
方式1:
super(当前类名称,self).你要调的父类的属性或方法
方式2:
super().你要调的父类的属性或方法
方式3:
类名称.你要调的父类的属性或方法(self)
#方式3与继承无关,是直接使用类名去调用了
组合:
其也是一种关系描述的什么有什么的关系。
例如:学生有手机
组合就是一个对象可以当作另一个对象的属性,大大降低了程序的耦合度。
目的:
也是为了重用代码。
什么时候使用继承:什么是什么的关系
什么时候使用组合:就是什么有什么的关系,这2个类之间没有太大的关系,完全不属于同类。
这个时候就是降低了耦合度。