python語言的鴨子類型和強類型語言的多態

python語言的鴨子類型和強類型語言的多態python

 

  前面講接口類的時候舉過一個有關支付方式的例子,支付方式能夠有幾種,微信支付,支付寶支付,蘋果支付等,這幾個不一樣的支付都統一於支付,像這樣幾個類都統一於微信

某一個類或者某一個方法,或者說一個類有不一樣的形態的狀況就屬於多態;雖然幾種支付方式都歸一於支付類,執行的方法同樣,可是每個支付方式都有本身的特性,實現的app

形態也不同,即爲多態性。微信支付

class Payment:  # 必要的父類
    def pay(self,money):
        pass
class Wechatpay(Payment):  # 子類繼承父類 
    def pay(self,money):
        print('已經使用微信支付了%s元' % money)

class Alipay(Payment):  # 子類繼承父類
    def pay(self,money):
        print('已經使用支付寶支付了%s元' % money)

class Aapplepay(Payment):  # 子類繼承父類
    def pay(self,money):
        print('已經使用蘋果支付了%s元' % money)

def pay(pay_obj,money):  # 受到父類的約束,這裏的pay_obj只能傳入繼承了父類的子類
    # 統一支付入口,歸一化設計,無論使用哪一種方式,都統一於支付方法
    pay_obj.pay(money)

 

也能夠不用在前面加上一個父類對子類進行約束也能夠達到多態的效果spa

 
class Wechatpay():
    def pay(self,money):
        print('已經使用微信支付了%s元' % money)

class Alipay():
    def pay(self,money):
        print('已經使用支付寶支付了%s元' % money)

class Aapplepay():
    def pay(self,money):
        print('已經使用蘋果支付了%s元' % money)

def pay(pay_obj,money):  # 這裏的pay_obj對數據不敏感,只要是含有pay方法的均可以傳入
    # 統一支付入口,歸一化設計,無論使用哪一種方式,都統一於支付方法
    pay_obj.pay(money)

pay(Aapplepay(),10000)  # 這裏能夠隨意的傳入支付方式,只要傳入的方式裏面有歸一的pay方法

  由於在python裏面傳參的時候:def pay(pay_obj,money),對數據不敏感,因此能夠徹底不用藉助父類來表現出多態,像python這樣沒必要須要一個父類來約束子類就能夠造成多態的類型叫作鴨子類型。因此說python天生支持多態,屬於動態強類型語言。設計

可是其餘語言好比Java必須藉助class Payment父類來傳父類的數據類型才能夠,用父類來約束子類,若是傳的不是父類的數據類型則會報錯,這樣的類型狀況纔是屬於正真的多態,也就是強類型語言中的多態。code

  python(鴨子類型):不崇尚根據繼承所得來的類似,我只是本身實現本身的代碼就能夠了。若是兩個類恰好類似,並不產生父類的子類的兄弟關係就是鴨子類型。好比list 和tuple就是這樣的關係,它們自己有好多類似的方法,可是並無經過父類去約束而找出類似的地方,只是咱們本身寫代碼的時候自我約束。blog

  鴨子類型的優缺點:繼承

  優勢:鬆耦合,每一個類似的類之間都沒有影響,刪除或修改一個類的代碼不會影響其餘類的接口

  缺點:太隨意,只能本身寫代碼自覺約束

再用一個比較好理解的例子來講明python語言的鴨子類型和強類型語言的多態:list 和 tuple

鴨子類型:

class List():
    def __len__(self):pass
class Tuple():
    def __len__(self):pass
def len(obj):
    return  obj._len_()
l = Tuple()
len(l)  # 這裏的l能夠是列表也能夠是元祖,無論是那個均可以將參數傳入len中,只要含有len方法均可以傳入

強類型語言的多態:

class Foo:pass  # 必須有一個父類
class List(Foo):  # 子類要繼承父類
    def __len__(self):pass
class Tuple(Foo):  # 子類要繼承父類
    def __len__(self):pass
def len(obj):
    return  obj._len_()
l = Tuple()
len(l)  # 這裏的l只能是繼承了Foo的類,數據類型必須和Foo的同樣,若是上面的obj傳入的是list這裏的l也必須是list,不然會報錯

 總結:接口類和抽象類在python當中的應用點並非很是必要

相關文章
相關標籤/搜索