[super][繼承][面向對象][構造函數][多重繼承]

super()內置函數

父類的構造函數必須手動調用, 調用方式有2種:
1. MyParentClass.__init__(xxx)
2. super(MyClass, self).__init__(xxx)

區別在於: 1比較直觀, 在涉及多重繼承時, 可以手動控制父類構造函數的調用順序, 需要手動爲每個父類調用一次構造函數; 2比較靈活, 動態查找父類, 在涉及多重繼承時, 會自動調用各個直接父類的構造函數;

class A(object):
    def __init__(self):
        super(A, self).__init__()
        print '__init__ A'

class B(A):
    def __init__(self):
        super(B, self).__init__()
        print '__init__ B'

class C(B):
    def __init__(self):
        super(C, self).__init__()
        print '__init__ C'

class AA(object):
    def __init__(self):
        super(AA, self).__init__()
        print '__init__ AA'

class D(A, AA):
    def __init__(self):
        super(D, self).__init__()
        print '__init__ D'

d = D()
# 自動調用所以直接父類的構造函數
#__init__ AA
#__init__ A
#__init__ D

class BB(A):
    def __init__(self):
        print '__init__ BB'

class CC(BB):
    def __init__(self):
        super(CC, self).__init__()
        print '__init__ CC'

cc = CC()
# super()只會查找直接父類, 不會遞歸查找, 所以, 因爲BB沒有調動super, 所以A的構造函數就被調用
#__init__ BB
#__init__ CC

c = C()
# 當前類和父類都調用了super, 所以才能保證繼承鏈上的所有構造函數都被調用
#__init__ A
#__init__ B
#__init__ C

三角繼承

# 直接報錯
class A:
    pass

class B(A):
    pass

class C(B, A):
    pass

c = C()
#TypeError: Error when calling the metaclass bases
    #Cannot create a consistent method resolution
#order (MRO) for bases B, A

報錯原因

C繼承A和B, 同時B也繼承A, 對C來說, B和A是它的2個直接父類, 所以C在進行方法查找時, A和B具有相同的優先級, 但是這時候問題就來了:
1. 如果先從A再B, 那麼B會覆蓋A的方法(當然了, 這是我們所期望的, 因爲B是A子類, 子類覆蓋父類, 是理所當然的)
2. 如果先從B再A, 那麼A會覆蓋B的方法(出錯了吧! 父類方法怎麼可以覆蓋子類方法呢!)

以上2種情況均可能出現, 這導致了方法解析順序(MRO)不一致

解決方法

既然B繼承A, 那麼B已經包含了A的全部內容, 所以直接繼承B就可以了, 沒有必要繼承A了:

class C(B):
    pass

萬事大吉!

菱形繼承

class A(object):
    def __init__(self):
        super(A, self).__init__()
        print '__init__ A'

class B(A):
    def __init__(self):
        super(B, self).__init__()
        print '__init__ B'

class C(A):
    def __init__(self):
        super(C, self).__init__()
        print '__init__ C'

class D(B, C):
    def __init__(self):
        super(D, self).__init__()
        print '__init__ D'
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章