物件導向 -- 三大特性之繼承

想吃橙子發表於2019-03-27

什麼是繼承

繼承就是一種建立新類的方式,在python中,新建的類可以繼承一個或多個父類,父類又可稱為基類或超類,新建的類稱為子類或派生類

輸入沒有指定父類,python的類會預設繼承object類,object是所有python類的父類。

單繼承

一個子類繼承了一個父類

如果子類想使用一個名字

如果子類自己有,那就用自己的

如果子類自己沒有,那就用父類的

如果父類也沒有,就報錯

如果想使用的名字子類和父類中都有

既想使用子類的,也想使用父類的 那就在子類的方法中使用

1.父類名.方法名(self.引數1,引數2)

2.super().方法名(引數1,引數2)

示例函式

class Animal(object):
    def __init__(self,name,kind):
        self.name = name
        self.kind = kind

    def eat(self,food):
        print('%s eat %s'%(self.name,food))

    def drink(self):
        print('%s drink water'%(self.name))

    def catch(self):
        print('%s catch mouse'%(self.name))


#
class Cat(Animal):
    def __init__(self,name,kind,eyes_color):
        self.eyes_color = eyes_color  # 派生屬性
        # super(Cat,self).__init__(name,kind)
        super().__init__(name,kind)   # 相當於執行父類的init方法
        # Animal.__init(self,name,kind)

    def climb(self):              # 派生方法
        print('%s climb tree'%self.name)

class Dog(Animal):
    def chai(self):
        print('%s cha'%(self.name))


hua = Cat('小花','橘貓','藍色')
hua.eat('小魚乾')
hua.climb()

組合和繼承的區別:

組合是什麼有什麼

繼承是什麼是什麼的關係

先想描述的物件

先寫出物件所對應的類

發現多個類之間有相同的程式碼

把相同的類提取出來,搞成一個父類

先抽象 再繼承

物件 -- 類 -- 父類

 

父類 -- (繼承) -- 子類 -- (例項化) -- 物件

 

繼承是基於抽象的結果,通過程式語言去實現它,肯定是先經歷抽象這個過程,才能通過繼承的方式去表達出抽象的結構

 

多繼承

是python特有的

class ShenXian: # 神仙
    def fei(self):
        print("神仙都會⻜")
class Monkey: #
    def chitao(self):
        print("猴⼦喜歡吃桃⼦")
class SunWukong(ShenXian, Monkey): # 孫悟空是神仙, 同時也是⼀只猴
    pass
sxz = SunWukong() # 孫悟空
sxz.chitao() # 會吃桃⼦
sxz.fei() # 會⻜

如果物件使用名字,是子類中有的,那麼一定用子類的

子類沒有,可以到多個父類中去尋找

但如果多個父類中出現了重名的方法時,可以通過 mro() 方法來判斷使用哪一個父類中的方法

鑽石繼承

 

查詢方法順序 D -- B -- C -- A

 

廣度優先
    C3演算法
99%的情況都可以用眼睛看出來
但是仍然有1%的情況是看不出來的

C3演算法是怎麼計算的
class A(object):
    def func(self):
        print('a')

class B(A):
    pass
    def func(self):
        print('b')

class C(A):
    pass
    def func(self):
        print('c')
class F:
    pass
    def func(self):
        print('f')

class D(A,F):
    pass
    # def func(self):
    #     print('d')

class E(B,C,F):
    pass
    def func(self):
        print('e')

class G(C,D):
    pass
    def func(self):
        print('g')

class H(E,G):
    pass
    def func(self):
        print('h')

print(H.mro())   # 就是幫助我們來展示c3演算法的繼承順序


C3演算法
A= [AO]
B = B ,B節點的父類對應的順序
B = B ,A節點順序
B = B ,[AO]
提取第一個點
    如果從左到右第一個類,
    在後面的繼承順序中也是第一個,或者不再出現在後面的繼承順序中
    那麼就可以把這個點提取出來,作為繼承順序中的第一個類
B = [AO]
BA = [O]
B這個節點的繼承順序 :[BAO]

C = C,[AO]
C = [AO]
CA = [O]
C這個節點的繼承順序 :[CAO]

l(D) = D + [BAO]
D = [BAO]
[DBAO]

l(E) = E + [CAO]
[ECAO]

L[F] = F,[DBAO],[ECAO]
[F] = [DBAO],[ECAO]
[FD] = [BAO],[ECAO]
[FDB] = [AO],[ECAO]
[FDB] = [AO],[ECAO]
[FDBE] = [AO],[CAO]
[FDBEC] = [AO],[AO]
[FDBECA] = [O],[O]
[FDBECAO]

以上演算法也可以用  print(子類.mro()) 來完成  這個程式碼是用來幫助我們展示C3演算法的繼承順序的

super的區別

單繼承中的super就是找父類

多繼承中的super找的時mro順序的下一分類  super之和mro順序有關  和父類子類無關

多繼承種類的區別

新式類

所有的類繼承的都是object

在python2x中 主動繼承object的才是新式類,否則預設是經典類

遵循廣度優先演算法 C3演算法

有 super 的類  super遵循mro順序 有mro()方法

經典類

不繼承object

多個類之間尋找方法時遵循深度優先

沒有super方法 沒有mro方法

 

相關文章