笨办法学Python3 ex44 学习笔记

第44个练习是关于继承。
第一个例子讲的是隐式继承,什么是隐式继承呢?简单地说,当A类中存在的特性或方法X,而B类中没有定义,直接从A类中继承得来,这种方式得继承就是隐式继承。
如下面得代码ex44a.py:

class Parent(object):

    def implicit(self):
        print("PARENT implicit()")

class Child(Parent):
    pass

if __name__ == "__main__":
    dad = Parent()
    son = Child()

    dad.implicit()
    son.implicit()

在Parent类中定义了一个一个implicit的方法,作用是打印出PARENT implicit(),而在Child类中,并没有新写任何新的方法和特性,直接继承Parent类中的所有方法和特性,这就是隐式继承。
注意的是,该处的code中,与原文不一致的地方是加了一个if __name__ == "__main__", 主要的目的是复习一下前面所学到的内容。在直接运行这段代码的时候,将按照原来的形式输出。而如果采用import模块的方式,则不会打印出任何文字。
输出的结果是:

PARENT implict()
PARENT implict()

第二个例子是在子类中重写父类的方法或特性。有的时候,子类中包含有和父类中同样名字的方法或特性,但是方法或特性的细节并不一样,采用隐式继承就无法实现子类对该方法或特性的需求,此时就需要在子类中重写该方法或特性。
在子类中重写的方法或特性将覆盖掉父类中同名的方法,这就是显式覆盖
代码如下ex44b.[y所示:

class Parent(object):

    def override(self):
        print("PARENT override()")

class Child(Parent):

    def override(self):
        print("CHILD override()")

if __name__ == "__main__":
    dad = Parent()
    son = Child()

    dad.override()
    son.override()

代码运行的结果是:

PARENT override()
CHILD override()

在Parent()和Child()中含有相同的方法override,此时虽然Child()是Parent()的子类,但是重写的方法将覆盖掉父类中同样名字的方法,使子类保持有新的方法或特性。

第三点涉及到是否直接采用子类的方法或特性(显示覆盖)还是在运行子类的方法或特性之前,首先运行父类的方法。我猜是有的场合,不能完全忽略掉父类中的方法和特性。这个时候就用到了super()函数。
代码如下面的ex44c.py中所示。

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()")

if __name__ == "__main__":
    dad = Parent()
    son = Child()

    dad.altered()
    son.altered()

运行的结果如下:

PARENT altered()
CHILD, BEFORE PARENT altered()
PARENT altered()
CHILD, AFTER PARENT altered()

第一个PARENT altered()比较好理解,这是直接调用父类Parent(object)中的alter方法得到的。
结果第二行中的CHILD, BEFORE PARENT altered()是第二个例子中的显示覆盖得到的结果。
真正有意思的是结果的第三行和第四行,这两行的结果是由super(Child,self).altered()运行得到的结果。对于显式覆盖,重写的altered()方法被直接调用,不用再管其继承的父类中的信息。而用super(Child,self).alter(),将会去访问其父类,并返回父类中的alter()方法。
可以想想采用这种继承的方式,在实际编程的时候有什么用处,现在mark一下,因为我也没有合适的例子。总之,如书中所讲,这种方式,可以在父类方法/特性运行后再用子类的方法/特性进行替换。
下面是三种方式组合使用的代码ex44d.py.

class Parent(object):

    def override(self):
        print("PARENT override()")

    def altered(self):
        print("PARENT altered()")

    def implicit(self):
        print("PARENT implicit()")

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()

运行的结果如下:

PARENT implicit()
PARENT implicit()
PARENT override()
CHILD override()
PARENT altered()
CHILD, BEFORE PARENT altered()
PARENT altered()
CHILD, AFTER PARENT altered()

到了这里,就要问一句:super()函数的意义在什么地方?因为隐式继承和显式覆盖这两种方式可以保证对父类中方法/特性的继承和重写,看起来功能都是足够了。但考虑到多重继承的情况,实际的情况可能相当复杂,例如当某个子类继承了多个父类,Child(P1,P2,P3,…),而这些父类之间可能有相同的方法/特性,或它们之间也有继承的关系,这样的继承关系就相当的复杂。在super机制里可以保证公共父类仅被执行一次,至于执行的顺序,是按照MRO(Method Resolution Order):方法解析顺序 进行的。

重点标记:

-super()最常见的用法是在父类的__init__函数中使用。通常这也是唯一可以进行这种操作的地方。
-可以直接使用别的类和模块,而非依赖于隐式继承。
-不惜一切代价去避免多重继承。
-需要代码复用的地方,可以通过组合做成模块。

你可能感兴趣的:(笨办法学Python3 ex44 学习笔记)