什么是继承?
继承的用处,就是用来指明一个类的大部分或全部功能,都是从一个父类中获得的,当你写成class Foo(Bar)时,代码就发生了继承效果,这句代码的意思是“创建一个叫Foo的类,并让他继承Bar”,当你这样写时,python语言会让Bar的实例具有的功能都工作在Foo的实例上,这样可以让你把通用的功能放到Bar里边,然后在给Foo特别设定一些功能
隐式继承
首先在父类里定义了一个函数,但没有在子类中定义的例子,这时候会发生隐式继承
代码如下
# coding: utf-8
__author__ = 'www.py3study.com'
class Parent(object):
def implicit(self):
print("PARENT implicit")
class Child(Parent):
pass
dad = Parent()
son = Child()
dad.implicit()
son.implicit()
应该看到的结果
class Child:中的pass是在python中创建空的代码区块方法,这样就创建了一个叫Child的类,但没有在里边定义任何细节,在这里它会从它的父类中继承所有的行为,运行起来就是这样(上图)
这就说明,如果你将函数放到基类中(也就是这里的Parent),那么所有的子类(也就是Child这样的类)将会自动获得这些函数功能。如果你需要很多类的时候,这样可以让你避免重复写很多代码
显示覆写(Explicit Override)
有时候你需要让子类里的函数有一个不同的行为,这种情况下隐式继承是做不到的,而你需要覆写子类中的函数,从而现实它的新功能,你只要在子类Child中定义一个相同名称的函数就可以了
代码如下:
# coding: utf-8
__author__ = 'www.py3study.com'
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()
应该看到的结果
如你所见,子类中新定义的函数在这里取代了父类的函数(也就是覆写)
在运行前或运行后覆写
第三种继承的方法是一个覆写的特例,这种情况下,你想在父类中定义的内容运行之前或者之后再修改的行为。首先你像上例一样覆写函数,不过接着你用python的内置函数super来调用父类Parent里的版本
代码如下
# coding: utf-8
__author__ = 'www.py3study.com'
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,改写了")
dad = Parent()
son = Child()
dad.altered()
son.altered()
应该看到的结果
super(Child, self).altered() 调用super并且加上Child和self这两个参数,在此返回的基础上然后调用alterrd.
super这种方法会知道你继承的关系,所以结果就是执行了父类的altered函数里面的print("PARENT altered()")
一起使用三种方式代码如下:
# coding: utf-8
__author__ = 'www.py3study.com'
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()
应该看到的结果
为什么要用super()
多重继承(Multiple Inheritance)的麻烦东西,多重继承是指你定义的类继承了多个类,就像这样
class SuperFun(Child, BadStuff):
pass
这相当于说"创建了一个叫SuperFun的类,让它同时继承Child和BadStuff"
Super()这个函数,就是应用这种场合,使用Super()函数python会自己找到正确的函数
super()和__init__搭配使用
最常见的super()的用法是在基类的__init__函数中使用,通常这也是唯一可以进行这种操作的地方,在这里你在子类里做了一些事情,然后完成对父类的初始化,示例代码如下
class Child(Parent):
def __init__(self, stuff):
self.stuff = stuff
super(Child, self).__init__()
这和上面的Child.altered差别不大,只不过在__init__里边先设了个变量,然后才用Parent.__init__初始化了Parent
合成
继承是一种有用的技术,不过还有一种实现相同功能的方法,就是直接使用别的类和模块,而非依赖于继承
示例代码如下
# coding: utf-8
__author__ = 'www.py3study.com'
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()
应该看到的结果
这里没有使用Parent这个名称,因为这里不是父类子类的"A是B"的关系,而是一个"A里有B"的关系,这里Child里有一个Other用来完成它的功能
继承和合成的应用场合
“继承vs合成”的问题说到底还是关于代码重用的问题,你不想到处都是重复的代码,这样既难看又没效率。继承可以让你在基类里隐含父类的功能,从而解决了这个问题。而合成则是利用模块和别的类中的函数调用实现了相同的目地
如果两种方案都能解决重用的问题,那什么时候该用哪个呢?这个问题的答案其实是非常主观的,推荐三个大体的指引方案
1 不惜一切代价地避免多重继承,它带来的麻烦比能解决的问题都多,如果你非要用,拿你得准备好专研类的层次结构,以及花时间去找各种东西的来龙去脉
2 如果你有一些代码会在不同位置和场合应用到,那就用合成来把它们做成模块
3 只有在代码之间有清楚的关联,可以通过一个单独的共性联系起来的时候使用继承
常见问题
怎么样增强自己解决新问题的技术?
提高解决问题能力的唯一方法就是自己去努力解决尽可能多的问题,很多时候人们碰到难题就会跑去找人给出答案,当你没时间需要尽快解决的时候,这样做是没有问题的,但是如果时间足够,那就花时间自己解决吧
对象是不是就是类的拷贝?
有的语言里是这样的,例如javascript,这样的语言叫做prototype语言,这种语言里的类和对象除了用法以外没多少不同。不过在python里类其实像是用来创建对象的模版,就跟制作硬币用到的模具一样