• 一、概念

子类可以拥有多个父类,并且具有所有父类的属性和方法

语法:

          class  子类名(父类名1, 父类名2......)

                  pass                                          

class A:def test(self):
        print("test 方法")class B:def demo(self):
        print("demo 方法")class C(A, B):# 多继承可以让子类对象,同时具有多个父类的属性和方法pass# 创建子类对象
c = C( )
c.test( )
c.demo( )
---------------------------
test 方法
demo 方法

以上程序中C类对象可以调用二个父类的方法。

二、多继承的使用注意事项:

如果不同父类中存在同名的方法,子类对象在调用方法时,会调用哪一个父类中的方法呢?

开发时,应该尽量避免这种容易产生混淆的情况

class A:def test(self):
        print("A---test 方法")def demo(self):
            print("A---demo 方法")class B:def test(self):
        print("B---test 方法")def demo(self):
        print("B---demo 方法")class C(A, B):# 多继承可以让子类对象,同时具有多个父类的属性和方法pass# 创建子类对象
c = C()
c.test()
c.demo()
---------------------------
A---test 方法
A---demo 方法

这程序在运行时,在调用同样的方法时,结果为A类中的方法。

如果把 class C(A,B)  改成    class C(B,A) ,运行的结果就是

B---test 方法

B---demo 方法

三、Python 中的MRO----方法搜索顺序:

  • Python 中针对类提供了一个内置属性__mro__可以查看方法搜索顺序
  • MRO是method resolution order,主要用于在多继承时判断方法、属性的调用路径

在上面的程序最后,加上

#确定C类对象调用方法的顺序print(C.__mro__)

运行结果:

A---test 方法
A---demo 方法
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
  • 在搜索方法时,是按照__mro__的输出结果从左到右的顺序查找的。
  • 如果在当前类中,找到方法,就直接执行,不再搜索。
  • 如果没有找到,就查找下一个类中是否有对应的方法,如果找到,就直接执行,不再搜索。
  • 如果找到最后一个类,还没有找到方法,程序报错。

四、新式类与旧式(经典)类、

object是Python为所有对象提供的基类,提供有一些内置的属性和方法,可以使用dir函数查看

  • 新式类:以object为基类的类,推荐使用
  • 经典类:不以object为基类的类,不推荐使用

在python3.x中定义类,如果没有指定父类,会默认使用object作为该类的基类--新式类

在python2.x中定义类时,如果没有指定父类,则不会以object作为基类

今后在定义类时,如果没有父类,建议统一继承自 object

            class  类名 (object)

                  pass          

五、多态:

面向对象三大特性:

1、封装根据职责将属性和方法封装到一个抽象的中(定义类的准则)

2、继承实现代码的重用,相同的代码不需要重复的编写

  • 设计类的技巧
  • 子类针对自己特有的需求,编写特定的代码

3、多态不同的子类对象调用相同的父类方法,产生不同的执行结果

  • 多态可以增加代码的灵活度
  • 继承重写父类方法为前提
  • 是调用方法的技巧,不会影响到类的内部设计

六、多态案例演练:

1、在Dog类中封装方法game

  • 普通狗只是简单的玩耍

2、定义XiaoTianDog继承自Dog,并且重写game方法

  • 哮天犬需要在天上玩耍

3、定义person类,并且封装一个和狗玩的方法

  • 在方法内部,直接让狗对象调用game方法
class Dog(object):def __init__(self, name):self.name = namedef game(self):
        print("%s 蹦蹦跳跳的玩耍!"% self.name)class XiaoTianDog(Dog):def game(self):
        print("%s 飞到天上去玩耍"% self.name)class Person(object):def __init__(self, name):self.name = namedef game_with_dog(self, aaa):
        print("%s 和 %s 快乐的玩耍..."% (self.name, aaa.name))# 让狗玩耍
        aaa.game()# 1. 创建一个狗对象# wangcai = Dog("旺财")
wangcai = XiaoTianDog("飞天旺财")# 2. 创建一个小明对象
xiaoming = Person("小明")# 3. 让小明调用和狗玩的方法
xiaoming.game_with_dog(wangcai)
-------------------------------
小明 和 旺财 快乐的玩耍...
旺财 蹦蹦跳跳的玩耍!
---------------------------
小明 和 飞天旺财 快乐的玩耍...
飞天旺财 飞到天上去玩耍

以上程序中,def game_with_dog(self, aaa),修改了,原来的aaa是dog,怕与前面的dog混淆从程序的二次运行结果看,有所不同

第一次是创建的狗对象,所以在调用方法中aaa.game()时,aaa是调用的普通狗的方法。

第二次是创建的哮天犬的对象,所以在调用方法中aaa.game()时,aaa是调用哮天犬的方法。