面向对象三大特征:封装 继承 多态

  面向对象的两大核心概念:类和对象

一、封装

  打包,包装, 包裹……
  面向对象编程的第一步: 讲究将方法和属性封装到一个类中

二、继承

  类与类之间存在了继承关系, 子类就可以继承父类的公有属性和公有方法

  子类: 派生类,拓展类,subclass
  父类: 超类,基类,superclass


  属性的覆盖: 子类中覆盖父类中的类属性
  派生属性: 子类中新增的, 父类中没有的属性

  1、继承性

    (1)子类可以继承父类的属性和方法
    (2)子类可以新增自己的属性和方法
    (3)子类可以重写父类已有的方法
      如果需要调用父类的功能, 使用super().方法名()

  2、意义
    (1)提高代码的重用性
    (2)拓展类的功能

 1 # 惯性写法
 2      父类: __init__(self, 参数1, 参数2,..):
 3                 self.属性1 = 参数1
 4                 self.属性2 = 参数2
 5                 ....
 6      子类: __init__(self, 参数1, 参数2,....)
 7                 super().__init__(参数1, 参数2,...)
 8                 self.新增属性 = 参数
 9 
10 # 子类继承父类, 如果子类中没有init方法, 创建子类对象时, 会自动调用父类的init方法;
11 # 子类继承父类, 如果子类中有init方法, 创建对象时, 就不会调用父类的init方法了,
12 # 如果需要使用父类的init方法, 则程序员需要手动调用super().__init__(参数1, 参数2,...)

  3、多继承

    (1)多继承:子类具有多个父类的情况,子类可以继承多个父类的功能。

    (2)python: (继承的传递)
      多层继承: 子类 --> 父类 --> 爷爷类 --> 祖先类 ---> object类   

    (3)python中支持多继承:多个父类,子类可以同时拥有多个父类功能。  

    (4)python2:c3算法 , 深度优先;python3:c3算法, 广度优先

      如果使用多继承(一个子类同时继承自多个父类), 保证父类中没有相同名字的方法;
        method resolution order

      可以根据 类.__mro__属性查看 当前类的父类的排序
      也可以根据 类.mro() 查看当前类的父类的排序

 1 class A:
 2     def func1(self):
 3         print("A")
 4 
 5 class B:
 6     def func1(self):
 7         print("B")
 8 
 9 class C:
10     def func1(self):
11         print("C")
12 
13 class D(A, B, C):
14     pass
15 
16 d = D()
17 d.func1()  # A
18 print(D.__mro__)  # (<class '__main__.D'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class 'object'>)
19 print(D.mro())  # [<class '__main__.D'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class 'object'>]

三、多态

  1、以继承和重写为前提,形参为父类对象,执行时,由具体的对象执行相应的方法
  2、非继承关系,形参为对象,执行时,由具体的对象执行相应的方法

  (python鸭子类型:如果一只鸟, 长得像鸭子, 叫起来像鸭子, 走路也像鸭子, 那么我们就可以把他当做鸭子)

 1 class Father:
 2     def say(self):
 3         print("父亲喊儿子吃饭")
 4 
 5 
 6 class Son(Father):  # 子类继承自父类
 7     def say(self):   # 子类中重写父类的方法
 8         print("儿子主动回家吃饭")
 9 
10 
11 def func(obj):  # obj 是一个对象
12     if isinstance(obj, Father):  # 判断obj是否是Father类的对象
13         obj.say()
14     else:
15         print("不是父亲和儿子")
16 
17 
18 f = Father()
19 s = Son()
20 
21 func(f)  # 父亲喊儿子吃饭
22 func(s)  # 儿子主动回家吃饭
23 
24 
25 class Duck:
26     def say(self):
27         print("gaga")
28 
29 
30 def func2(obj):  # obj 是一个对象
31     obj.say()
32 
33 
34 d = Duck()
35 func2(d)  # 调用函数, 传参为鸭子类对象  gaga
36 func2(f)  # 调用函数, 传参为父亲类对象  父亲喊儿子吃饭
37 func2(s)  # 调用函数, 传参为儿子类对象  儿子主动回家吃饭