概述
面向对象三大特性:封装,继承和多态,
从字⾯理解就是多种形态 ⼀个对象可以以不同形态去呈现
⾯向对象三⼤特性:
- 封装 :确保对象中数据的安全
- 继承 :保证了对象的扩展性
- 多态 :保证了程序的灵活性
前面博客讲了封装,而这一章博客来讲讲继承,与多态
继承
继承提⾼了类的复⽤性。让类与类之间产⽣了关系。有了这个关系,才有了 多态的特性
在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Base class、Super class)
代码实战说明
# 垃圾类 父类
class Waste():
w_name = '垃圾'
# ‘垃圾’类的一个方法:回收垃圾
def recycle_w(self):
print('回收垃圾...')
# ‘有害垃圾’类 子类1
class Swaste(Waste): # 括号中填写父类的变量名
pass
# ‘可回收垃圾’类 子类2
class Gwaste(Waste):
pass
继承有什么好处?最大的好处是子类获得了父类的全部功能。Swaste和Gwaste就继承了Waste的全部功能
如下运行试试:
a1 = Waste() #实例化父类Waste
a2 = Swaste() #实例化子类1Swaste
a3 = Gwaste() #实例化子类2Gwaste
a1.recycle() #在父类中调用recycle()方法
a2.recycle() #在子类1中调用recycle()方法
a3.recycle() #在子类2中调用recycle()方法
结果为:
回收垃圾...
回收垃圾...
回收垃圾...
虽然Swaste和Gwaste两个类中没有实质代码块内容,但是他们继承了Waste类的功能,所以可以运行recycle()
# 垃圾类
class Waste():
w_name = '垃圾'
# ‘垃圾’类的一个方法:回收垃圾
def recycle(self):
print('回收垃圾...')
# ‘有害垃圾’类
class Swaste(Waste): # 括号中填写父类的变量名
def run1(self):
print('处理有害垃圾')
# ‘可回收垃圾’类
class Gwaste(Waste):
def run2(self):
print('回收可回收垃圾')
a1 = Waste() #实例化父类Waste
a2 = Swaste() #实例化子类1Swaste
a3 = Gwaste() #实例化子类2Gwaste
a1.recycle() #在父类中调用方法recycle()
a2.recycle() #在子类1中调用方法recycle()
a2.run1() #在子类1中调用方法run1()
a3.recycle() #在子类2中调用方法recycle()
a3.run2() #在子类2中调用方法run1()
回收垃圾...
回收垃圾...
处理有害垃圾
回收垃圾...
回收可回收垃圾
实例关系
istance()方法大家知道吧,来检查一个对象是否是一个对象的实例,那么子类既然继承了父类,那他们的的实例是否有关系呢?
附:object是所有类的父类
在创建类的时候省略父类的话默认即是object
# 垃圾类
class Waste():
w_name = '垃圾'
# ‘垃圾’类的一个方法:回收垃圾
def recycle(self):
print('回收垃圾...')
# ‘有害垃圾’类
class Swaste(Waste): # 括号中填写父类的变量名
pass
# ‘可回收垃圾’类
class Gwaste(Waste):
pass
# 创建‘有害垃圾’类的实例hw
sw = Swaste()
gw = Gwaste
print('子类的实例sw与父类的是否存在关联:')
print(isinstance(sw, Waste))
print('子类的实例gw与父类的是否存在关联:')
print(isinstance(gw, Waste))
print('子类的实例sw与‘object’类的是否存在关联:')
print(isinstance(sw, object))
print('子类的实例gw与‘object’类的是否存在关联:')
print(isinstance(gw, object))
print('结论:子类默认继承‘object’类,与其存在关联!')
子类的实例sw与父类的是否存在关联:
True
子类的实例gw与父类的是否存在关联:
False
子类的实例sw与‘object’类的是否存在关联:
True
子类的实例gw与‘object’类的是否存在关联:
True
结论:子类默认继承‘object’类,与其存在关联
issubclass()
issubclass()方法可以检查一个类是否另一个类的子类
# 垃圾类
class Waste():
w_name = '垃圾'
# ‘垃圾’类的一个方法:回收垃圾
def recycle(self):
print('回收垃圾...')
# ‘有害垃圾’类
class Swaste(Waste): # 括号中填写父类的变量名
def run1(self):
print('处理有害垃圾')
# ‘可回收垃圾’类
class Gwaste(Waste):
def run2(self):
print('回收可回收垃圾')
print(issubclass(Swaste,Waste))
print(issubclass(Swaste,Waste))
print(issubclass(Waste,object)) #object所有类的父类
True
True
True
方法的重写
如果在⼦类中有和⽗类同名的⽅法,则通过⼦类实例去调⽤⽅法时,会调⽤ ⼦类的⽅法⽽不是⽗类的⽅法,这个特点我们称之为⽅法的重写(覆盖)
上面的实例子类中的方法名都与父类中的方法名不同,但是如果取方法名一样呢,会如何执行呢?
# 垃圾类
class Waste():
w_name = '垃圾'
# ‘垃圾’类的一个方法:回收垃圾
def recycle(self):
print('回收垃圾...')
# ‘有害垃圾’类
class Swaste(Waste): # 括号中填写父类的变量名
def recycle(self): #与父类中的方法名相同
print('处理有害垃圾')
# ‘可回收垃圾’类
class Gwaste(Waste):
def recycle(self): #与父类中的方法名相同
print('回收可回收垃圾')
a1 = Waste()
a2 = Swaste()
a3 = Gwaste()
a1.recycle()
a2.recycle()
a3.recycle()
回收垃圾...
处理有害垃圾
回收可回收垃圾
我们发现上面实例中子类中的方法名与父类重合时,调用时用的是子类的方法,原理是什么呢?
- 当我们调⽤⼀个对象的⽅法时:
- 会优先去当前对象中寻找是否具有该⽅法,如果有则直接调⽤
- 如果没有,则去当前对象的⽗类中寻找,如果⽗类中有则直接调⽤⽗类中的⽅法
- 如果没有,则去⽗类中的⽗类寻找,以此类推,直到找到object,如果依然没有找到就报错了
- 如果没有,则去当前对象的⽗类中寻找,如果⽗类中有则直接调⽤⽗类中的⽅法
- 会优先去当前对象中寻找是否具有该⽅法,如果有则直接调⽤
- 这样,我们就获得了继承的另一个好处:多态。
多重继承
类的多重继承
在Python当中,定义一个类的时候可以同时继承多个父类,这种方式被称为多重继承
也就是我们可以为⼀个类同时制定多个⽗类 可以在类名的()后边添加多个类,来实现多重继承
多重继承,会使⼦类同时拥有多个⽗类,并且会获取到所有⽗类中的⽅法
在开发中没有特殊情况,应该尽量避免使⽤多重继承。因为多重继承会让我 们的代码更加复杂
如果多个⽗类中有同名的⽅法,则会先在第⼀个⽗类中寻找,然后找第⼆ 个,找第三个…前⾯会覆盖后⾯的
class A(object):
def run1(self):
print('A')
class B(object):
def run2(self):
print('B')
class C(A,B): #C继承了A与B
pass
c = C()
c.run1() #继承的A的方法
c.run2() #继承的B的方法
结果:
A
B
super()
super()可以获取当前类的⽗类
并且通过super()返回对象调⽤⽗类⽅法时,不需要传递self
在子类继承父类时,也会继承父类的特殊方法,比如初始化方法__init__,但是因为方法重写问题会在使用时出现一些不便,那么可以使用super方法来解决一些问题
# 垃圾类
class Waste():
def __init__(self,name):
self.name = name
# ‘垃圾’类的一个方法:回收垃圾
def recycle(self):
print('回收垃圾...')
# ‘有害垃圾’类
class Swaste(Waste): # 括号中填写父类的变量名
def __init__(self,name,kind):
super().__init__(name)
self.kind = kind
def recycle(self):
print('处理',self.kind,self.name)
# ‘可回收垃圾’类
class Gwaste(Waste):
def recycle(self):
print('回收可回收',self.name)
a1 = Waste('垃圾')
a2 = Swaste('垃圾','有害')
a3 = Gwaste('垃圾')
a1.recycle()
a2.recycle()
a3.recycle()
回收垃圾...
处理 有害 垃圾
回收可回收 垃圾
如上实例,子类中多了新的__init__方法,但是使用super方法直接使用父类中的__init__方法,所以子类中的__init__方法使用的是父类中的方法
多态
Python中多态的特点
1、只关心对象的实例方法是否同名,不关心对象所属的类型;
2、对象所属的类之间,继承关系可有可无;
3、多态的好处可以增加代码的外部调用灵活度,让代码更加通用,兼容性比较强;
4、多态是调用方法的技巧,不会影响到类的内部设计。
- 多态是⾯向对象的三⼤特性之⼀。
从字⾯理解就是多种形态 ⼀个对象可以以不同形态去呈现
我们再编写一个函数帮助我们来理解多态
class dog(object): #狗类
def run(self):
print('狗在地板上跑')
class pig(object): #猪类
def run(self):
print('猪在田野上跑')
class cat(object): #猫类
def run(self):
print('猫在床上跑')
def run(obj): #实现跑的函数
obj.run()
dog = dog()
run(dog)
pig = pig()
run(pig)
cat = cat()
run(cat)
结果:
狗在地板上跑
猪在田野上跑
猫在床上跑
从继承的角度举例子:
class gradapa(object): #祖父类
def __init__(self, money): #初始工资
self.money = money
def p(self):
print("this is gradapa")
print('工资是', self.money)
class father(gradapa): #父亲类
def __init__(self, money, job):
super().__init__(money)
self.job = job #加上职业
def p(self):
print("this is father,我重写了父类的方法")
print('工资是', self.money)
class mother(gradapa): #母亲类
def __init__(self, money, job):
super().__init__(money)
self.job = job
def p(self):
print("this is mother,我重写了父类的方法")
print('工资是',self.money)
def fc(obj): #定义函数调用类中的方法
obj.p()
gradapa1 = gradapa(3000)
father1 = father(2000, "工人")
mother1 = mother(1000, "老师")
fc(gradapa1) # 这里的多态性体现是向同一个函数,传递不同参数后,可以实现不同功能.
fc(father1)
print(fc(mother1))
结果:
this is gradapa
工资是 3000
this is father,我重写了父类的方法
工资是 2000
this is mother,我重写了父类的方法
工资是 1000
None