![69edcf83953247882083d54bf971a894.png](https://i-blog.csdnimg.cn/blog_migrate/4915e5ddca1f63d21e67adbf1d5fa580.png)
笨方法”学Python3,习题 44:继承与组合
1、什么是继承 ?
2、什么是组合 ?
3、它们的区别是什么 ?
一、什么是继承
### 继承就是用来指明一个类的大部分或者全部功能都是从一个父类中获得的,如 class Foo(Bar) 这种形式就发生了继承效果,Foo 类就继承了它的父类 Bar 的功能,这样子我们就可以把通用的功能发在父类 Bar 中,然后特定的功能放在子类 Foo 中
- 父子类的交互方式:
1、子类上的动作完全等同于父类上的动作
2、子类上的动作完全覆盖了父类上的动作
3、子类上的动作部分替换了父类上的动作
隐式继承
- 例子:
所写的代码:
class Parent(object):
def implicit(self):
print("PARENT implicit()")
class Child(Parent):
pass
dad = Parent()
son = Child()
dad.implicit()
son.implicit()
---------------------------------------------------------------------------------------------------
应该看到的结果:
PS D:代码> & D:/软件/python/python.exe d:/代码/ex44a.py
PARENT implicit()
PARENT implicit()
![fd664ae9982f28f7d8e2b95b8e02ea06.png](https://i-blog.csdnimg.cn/blog_migrate/8526e8f7f9f1cb233859b13f66486e3a.png)
- 说明:
可以看出子类 Child 中使用了 pass,里面并没有定义 implicit 函数,但是子类依然可以调用 implicit 函数。可见,父类中的函数子类可以通过继承来自动获取这些函数,这样子我们就可以将一些通用的函数放在父类中来避免写许多重复的代码
显式覆盖
- 例子:
所写的代码:
class Parent(object):
def override(self):
print("PARENT override()")
class Child(Parent):
def override(self):
print("CHILD override()")
dad = Parent()
son = Child()
dad.override()
son.override()
---------------------------------------------------------------------------------------------------
应该看到的结果:
PS D:代码> & D:/软件/python/python.exe d:/代码/ex44b.py
PARENT override()
CHILD override()
![7eb65b17b47d2998a4a8c3dab5fab850.png](https://i-blog.csdnimg.cn/blog_migrate/6e9bb1c28823deaec45614b666ba7ccb.png)
- 说明:
隐形继承有个问题就是想让子类里的函数有不同行为时该怎么办,这时候可以覆盖子类中的函数,给它定义新功能。在例子中可以看出,在子类 Child 中定义一个同名的函数而函数内行为与父类中的不一样就实现了覆盖的作用。
在运行前或运行后替换
- 例子:
所写的代码:
class Parent(object):
def altered(self):
print("PARENT altered()")
class Child(Parent):
def altered(self):
print("CHILD, BEFORE PARENT altered()")
super(Child, self).altered()
print("CHILD, AFTER PARENT altered()")
dad = Parent()
son = Child()
dad.altered()
son.altered()
---------------------------------------------------------------------------------------------------
应该看到的结果:
PS D:代码> & D:/软件/python/python.exe d:/代码/ex44c.py
PARENT altered()
CHILD, BEFORE PARENT altered()
PARENT altered()
CHILD, AFTER PARENT altered()
![0a047f63258ca7c47f65d4c432d2d9eb.png](https://i-blog.csdnimg.cn/blog_migrate/8f3ffd6177893ac3c0910a3f8a857272.png)
- 说明:
可以看出第 9 行子类 Child 中实现了对 altered 函数的覆盖,但是第 10 行的 super 函数又实现了调用父类 Parent 中的 altered 函数,可见 super 函数可以根据里面的参数 Child 和 self 而得知 Child 的父类是 Parent,并且可以以此来调用父类中的函数
3 种方式组合使用
- 例子:
所写的代码:
class Parent(object):
def override(self):
print("PARENT override()")
def implicit(self):
print("PARENT implicit()")
def altered(self):
print("PARENT altered()")
class Child(Parent):
def override(self):
print("CHILD override()")
def altered(self):
print("CHILD, BEFORE PARENT altered()")
super(Child, self).altered()
print("CHILD, AFTER PARENT altered()")
dad = Parent()
son = Child()
dad.implicit()
son.implicit()
dad.override()
son.override()
dad.altered()
son.altered()
---------------------------------------------------------------------------------------------------
应该看到的结果:
PS D:代码> & D:/软件/python/python.exe d:/代码/ex44d.py
PARENT implicit()
PARENT implicit()
PARENT override()
CHILD override()
PARENT altered()
CHILD, BEFORE PARENT altered()
PARENT altered()
CHILD, AFTER PARENT altered()
![5dd7982787afcdc5697429ccb85c4b47.png](https://i-blog.csdnimg.cn/blog_migrate/bb32eba88f2a32355d76bdfe985af114.jpeg)
二、要用 super()的原因
### 什么是“多重继承”,类似这种 class SuperFun(Child, Badstuff) 一个类继承了一个或多个类就是“多重继承”。在这里子类 SuperFun 同时继承了父类 Child 和 BadStuff,当子类 SuperFun 要调用隐式动作时,Python 就必须去父类中按固定的顺序来查找可能的函数,为实现这一点,Python 使用了一个叫“方法解析顺序”(MRO)和一个叫 C3 的算法。我们只需要使用 super 函数来在需要修改的地方进行处理即可,大大避免了把继承关系弄糟
super()和 __init__ 搭配使用
super()最常见的用法就是在基类的 __init__ 函数中使用,通常这也是唯一可以进行这种操作的地方,要先在子类中完成以下操作才可以在父类中完成初始化。在这个例子中,只是在 __init__ 里设了一些变量,然后再让 Parent 用 Parent.__init__ 完成初始化
子类中所完成的操作:
class Child(Parent):
def __init__(self, stuff):
self.stuff = stuff
super(Child, self). __init__()
三、组合
### 我们可以直接使用别的类和模块而非依赖隐式继承来实现相同的功能
所写的代码:
class Other(object):
def override(self):
print("OTHER override()")
def implicit(self):
print("OTHER implicit()")
def altered(self):
print("OTHER altered()")
class Child(object):
def __init__(self):
self.other = Other()
def implicit(self):
self.other.implicit()
def override(self):
print("CHILD override()")
def altered(self):
print("CHILD, BEFORE OTHER altered()")
self.other.altered()
print("CHILD, AFTER OTHER altered()")
son = Child()
son.implicit()
son.override()
son.altered()
---------------------------------------------------------------------------------------------------
应该看到的结果:
PS D:代码> & D:/软件/python/python.exe d:/代码/ex44e.py
OTHER implicit()
CHILD override()
CHILD, BEFORE OTHER altered()
OTHER altered()
CHILD, AFTER OTHER altered()
可以看出两个类的内容很相近,其中 Child 中定义了一个 Child.implicit 函数来完成 Other 中的implicit 函数功能,其中 def __init__(self): self.other = Other() 似乎是两个类之间的桥梁,使得 Child 可以调用 Other 中的函数,若删去这段脚本则会报错(如下)
![9f578d706a764fec44d48d69e5c0b083.png](https://i-blog.csdnimg.cn/blog_migrate/b1bae623836b89a1c2d0c5dab74c4a6b.jpeg)
四、继承和组合的应用场合
二者都是为了解决代码复用的问题,继承通过创建一种让你在基类里隐含父类的功能的机制来解决问题,而组合则是利用模块和别的类中的函数调用达到相同目的
指导原则(不一定要遵循):
- 避免多重继承,太复杂了
- 代码在不同位置和场合可以应用到,用组合把它们做成模块
- 代码的可复用部分之间有清楚的关联或者必须要用继承时,用继承
五、巩固练习
阅读内容:https://www.python.org/dev/peps/pep-0008/
总结:
1、super 函数可以避免复杂的多重继承,其格式为 super(类名, self).函数名()
2、隐式继承,子类继承了父类的函数方法
3、显式覆盖,子类同名函数覆盖了继承的父类同名函数
^ v ^,知乎此系列文章内容均会在微信公众号中同步更新,公众号:小民有个小旮旯