(一)单继承:
在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类或派生类(Subclass),而被继承的class称为父类或基类(Base class、Super class)。
比如,我们已经编写了一个名为Animal的class,有一个eat()方法可以直接打印:
1 class Animal(object):
2 def eat(self):
3 print("Animal is eating")
当我们需要编写Dog或
Cat
类时,就可以直接从Animal
类继承:
1 class Dog(Animal):
2 pass
3
4
5 class Cat(Animal):
6 pass
对于Dog来说,Animal就是它的父类,对于Animal来说,Dog就是它的子类。Cat和Dog类似。
继承有什么好处?最大的好处是子类获得了父类的全部功能。由于Animial实现了eat()方法,因此,Dog和Cat作为它的子类,什么事也没干,就自动拥有了eat()方法:
1 d1 = Dog()
2 d1.eat()
3
4 c1 = Cat()
5 c1.eat()
运行结果如下:
1 Animal is eating
2 Animal is eating
当然,也可以对子类增加一些方法,比如Dog类:
1 class Dog(Animal):
2 def eat(self):
3 print("Dog is eating meat")
4
5 def bark(self):
6 print("Dog is barking")
当子类和父类都存在相同的eat()
方法时,我们说,子类的eat()
覆盖了父类的eat()
,在代码运行的时候,总是会调用子类的eat()
。这样,我们就获得了继承的另一个好处:多态。我们可以理解为子类把父类的代码复制到了自己里面。
此时 d1.eat() 的输出是: Dog is eating meat
我们再添加一个Hasky类继承Dog类,
1 class Hasky(Dog):
2 pass
当Hasky类的实例调用eat方法时,
1 h1 = Hasky()
2 h1.eat()
寻找eat方法遵循自下而上的顺序(我们把继承关系看成一颗倒立的树),因此运行结果是: Dog is eating meat
(二)多继承:
Python中允许一个类同时继承多个类,那么在阅读别人写的代码时就遇到一个问题,有时一个方法在多个类中都有实现,我们如何寻找正确的实现呢?
(1)首先看一个简单的例子,C1同时继承C2,C3:
1 class C3(object):
2 def f1(self):
3 print("C3.f1")
4
5
6 class C2(object):
7 def f1(self):
8 print("C2.f1")
9
10
11 class C1(C2, C3):
12 pass
13
14 obj_c1 = C1()
15 obj_c1.f1()
Python在寻找f1的实现时遵循从左至右的原则(选在C2里找,然后在C3里):
因此程序运行结果是: C2.f1
(2)我们再来看一个稍微复杂的例子,加入上例中C2还继承了一个C4类,而C3与C4对同一个方法f2都有实现,Python如何处理呢?
1 class C4(object):
2 def f2(self):
3 print("C4.f2")
4
5
6 class C3(object):
7 def f1(self):
8 print("C3.f1")
9
10 def f2(self):
11 print("C3.f2")
12
13
14 class C2(C4):
15 def f1(self):
16 print("C2.f1")
17
18
19 class C1(C2, C3):
20 pass
21
22 obj_c1 = C1()
23 obj_c1.f2()
按照上面的例1,Python首先在C2里寻找,而C2没有f2方法,这时有两条路,往上找C4,或者往右找C3,
从实际运行结果看,Python遵循深度优先原则,如下图所示:
程序运行结果: C4.f2
(3)我们再看一个相对复杂的例子,类继承关系如下图:
假如C5和C3里都有一个f3方法,代码如下:
1 class C5(object):
2 def f3(self):
3 print("C5.f3")
4
5
6 class C4(C5):
7 def f2(self):
8 print("C4.f2")
9
10
11 class C3(C5):
12 def f1(self):
13 print("C3.f1")
14
15 def f2(self):
16 print("C3.f2")
17
18 def f3(self):
19 print("C3.f3")
20
21
22 class C2(C4):
23 def f1(self):
24 print("C2.f1")
25
26
27 class C1(C2, C3):
28 pass
29
30 obj_c1 = C1()
31 obj_c1.f3()
那么obj_c1.f3()会使用哪个类的f3呢?按照我们在例2中深度优先的原则,应该是C5的f3,可是程序运行结果却是 C3.f3
这里有一个原因,当C4和C3有共同父类时,父类里是最后才寻找的。实际搜寻顺序如下图的数字: