前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >习题36:类的继承和合成

习题36:类的继承和合成

作者头像
py3study
发布2018-08-02 15:20:41
3550
发布2018-08-02 15:20:41
举报
文章被收录于专栏:python3

什么是继承?

继承的用处,就是用来指明一个类的大部分或全部功能,都是从一个父类中获得的,当你写成class Foo(Bar)时,代码就发生了继承效果,这句代码的意思是“创建一个叫Foo的类,并让他继承Bar”,当你这样写时,python语言会让Bar的实例具有的功能都工作在Foo的实例上,这样可以让你把通用的功能放到Bar里边,然后在给Foo特别设定一些功能

隐式继承

首先在父类里定义了一个函数,但没有在子类中定义的例子,这时候会发生隐式继承

代码如下

代码语言:javascript
复制
# 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中定义一个相同名称的函数就可以了

代码如下:

代码语言:javascript
复制
 # 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里的版本

代码如下

代码语言:javascript
复制
# 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()")

一起使用三种方式代码如下:

代码语言:javascript
复制
# 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

合成

继承是一种有用的技术,不过还有一种实现相同功能的方法,就是直接使用别的类和模块,而非依赖于继承

示例代码如下

代码语言:javascript
复制
# 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里类其实像是用来创建对象的模版,就跟制作硬币用到的模具一样

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017/12/02 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档