python精讲之面向对象(3)继承,多态

概述

面向对象三大特性:封装,继承和多态,

从字⾯理解就是多种形态 ⼀个对象可以以不同形态去呈现
⾯向对象三⼤特性:

  • 封装 :确保对象中数据的安全
  • 继承 :保证了对象的扩展性
  • 多态 :保证了程序的灵活性
    前面博客讲了封装,而这一章博客来讲讲继承,与多态

继承

继承提⾼了类的复⽤性。让类与类之间产⽣了关系。有了这个关系,才有了 多态的特性

在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

版权声明:本文为xdc1812547560原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。