zoukankan      html  css  js  c++  java
  • 48、面向对象中super的作用?

    什么是super

      super() 函数是用于调用父类(超类)的一个方法。
      super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。
      MRO 就是类的方法解析顺序表, 其实也就是继承父类方法时的顺序表。

    语法

    以下是 super() 方法的语法:

    super(type[, object-or-type])

    参数

      ·type -- 类。

      ·object-or-type -- 类,一般是 self

    Python3.x 和 Python2.x 的一个区别是: Python 3 可以使用直接使用 super().xxx 代替 super(Class, self).xxx :
    Python3.x 实例:

    class A:
        pass
    class B(A):
        def add(self, x):
            super().add(x)

    Python2.x 实例:

    class A(object):   # Python2.x 记得继承 object
        pass
    class B(A):
        def add(self, x):
            super(B, self).add(x)

    具体应用示例:

    举个例子

    class Foo:  
      def bar(self, message):  
        print(message)  
    >>> Foo().bar("Hello, Python.")  
    Hello, Python.

      当存在继承关系的时候,有时候需要在子类中调用父类的方法,此时最简单的方法是把对象调用转换成类调用,需要注意的是这时self参数需要显式传递,例如:

    class FooParent:  
      def bar(self, message):  
        print(message)  
    class FooChild(FooParent):  
      def bar(self, message):  
        FooParent.bar(self, message)  
    >>> FooChild().bar("Hello, Python.")  
    Hello, Python.

      这样做有一些缺点,比如说如果修改了父类名称,那么在子类中会涉及多处修改,另外,Python是允许多继承的语言,如上所示的方法在多继承时就需要重复写多次,显得累赘。为了解决这些问题,Python引入了super()机制,例子代码如下:

    class FooParent:  
      def bar(self, message):  
        print(message)  
    class FooChild(FooParent):  
      def bar(self, message):  
        super(FooChild, self).bar(message)  
      
    >>> FooChild().bar("Hello, Python.")  
    Hello, Python

      表面上看 super(FooChild, self).bar(message)方法和FooParent.bar(self, message)方法的结果是一致的,实际上这两种方法的内部处理机制大大不同,当涉及多继承情况时,就会表现出明显的差异来,直接给例子:
    代码一:

    class A:  
      def __init__(self):  
        print("Enter A")  
        print("Leave A")  
    class B(A):  
      def __init__(self):  
        print("Enter B")  
        A.__init__(self)  
        print("Leave B")  
    class C(A):  
      def __init__(self):  
        print("Enter C")  
        A.__init__(self)  
        print("Leave C")  
    class D(A):  
      def __init__(self):  
        print("Enter D")  
        A.__init__(self)  
        print("Leave D")  
    class E(B, C, D):  
      def __init__(self):  
        print("Enter E")  
        B.__init__(self)  
        C.__init__(self)  
        D.__init__(self)  
        print("Leave E")  
    E()

    结果为:

    Enter E
    Enter B
    Enter A
    Leave A
    Leave B
    Enter C
    Enter A
    Leave A
    Leave C
    Enter D
    Enter A
    Leave A
    Leave D
    Leave E

    执行顺序很好理解,唯一需要注意的是公共父类A被执行了多次。

    代码二:

    class A:  
      def __init__(self):  
        print("Enter A")  
        print("Leave A")  
    class B(A):  
      def __init__(self):  
        print("Enter B")  
        super(B, self).__init__()  
        print("Leave B")  
    class C(A):  
      def __init__(self):  
        print("Enter C")  
        super(C, self).__init__()  
        print("Leave C")  
    class D(A):  
      def __init__(self):  
        print("Enter D")  
        super(D, self).__init__()  
        print("Leave D")  
    class E(B, C, D):  
      def __init__(self):  
        print("Enter E")  
        super(E, self).__init__()  
        print("Leave E")  
    E()

    结果:
    Enter E
    Enter B
    Enter C
    Enter D
    Enter A
    Leave A
    Leave D
    Leave C
    Leave B
    Leave E

      在super机制里可以保证公共父类仅被执行一次,至于执行的顺序,是按照MRO(Method Resolution Order):方法解析顺序 进行的。

  • 相关阅读:
    "密码最短长度为7,其中必须包含以下非字母数字字符1"解决方法 (转)
    关于数据绑定的一个小小的总结:绑定数据到List类型的控件(RadioButtonList,ListBox等),双重绑定。
    转:从玩具到游戏 看另类项目激励机制
    [系列文章]上传文件管理控件之v1
    [系列文章]上传文件管理控件v3
    解决“此版本的 SQL Server 不支持用户实例登录标志。该连接将关闭”问题,完整综合版。
    Crystal Reports基本语法
    Crystal Reports图表(上)
    Crystal Reports第一张报表
    Crystal Reports中的字段
  • 原文地址:https://www.cnblogs.com/zhuifeng-mayi/p/9221562.html
Copyright © 2011-2022 走看看