繼承和多態

在OOP程序設計中,當定義一個class的時候,可從某個現有的class繼承
新的class稱爲子類(Subclass),而被繼承的class稱爲基類、父類或超類(Base class、Super class)
格式:函數

  class 子類名(父類名):
    pass

 

使用示例spa

class Animal(object):
    def run(self):
        print('Animal is running...')
    
class Dog(Animal):
    pass
    
class Dog1(Animal):
    def run(self):
        print('Dog is running...')
        
def run_twice(animal):  
    animal.run()  
    animal.run()
        
dog = Dog()
dog.run()    #輸出:Animal is running...

dog1 = Dog1()
dog1.run()    #輸出:Dog is running...,執行子類本身的方法

run_twice(Animal())
#輸出:Animal is running...
#輸出:Animal is running...

run_twice(Dog1())
#輸出:Dog is running...
#輸出:Dog is running...

#新追加一個子類型Tortoise,而後調用run_twice函數,依然能夠運行
class Tortoise(Animal):   
    def run(self):
        print('Tortoise is running slowly...')    
        
run_twice(Tortoise())   #調用run_twice函數,依然能夠運行,確保傳入的對象有run()方法便可
#輸出:Tortoise is running slowly...
#輸出:Tortoise is running slowly...

 

 

數據類型判斷
  定義一個class實際上就是定義一種數據類型,該數據類型和Python自帶的數據類型,好比str、list、dict徹底同樣
  判斷一個變量是不是某個類型能夠用isinstance()判斷
  對於isinstance(a, A),則
    若是a是A類對象,返回true
    若是a是A類子類對象,返回true
    其餘都返回false設計

 

關於繼承
  1) 繼承能夠把父類的全部功能都直接拿過來,這樣就沒必要重零作起,子類只須要新增本身特有的方法,也能夠把父類不適合的方法覆蓋重寫
   子類經過繼承得到了全部父類的方法(包括__init__方法,若是父類的該方法有參數,則子類建立實例時也要傳參數)
  2) 當子類和父類都存在相同的方法時,子類覆蓋了父類的該方法,運行時,老是會調用子類方法,這就是就是多態
  3) 繼承還能夠一級一級地繼承下來,就比如從爺爺到爸爸、再到兒子這樣的關係
    而任何類,最終均可以追溯到根類object,這些繼承關係看上去就像一顆倒着的樹code


關於多態
  調用方只管調用,無論細節,而當新增一種子類時,只要確保方法編寫正確,不用管原來的代碼是如何調用的
  說白了,就是無論怎麼追加子類,也不須要修改原來的代碼
  這就是著名的"開閉"原則:
    對擴展開放:容許子類重寫方法函數
    對修改封閉:不重寫,直接繼承父類方法函數對象

 

靜態語言和動態語言
  若是一個方法,要傳入的參數是A類對象,方法內部須要調用該參數的run()方法,則:
    對於Java這樣的動態語言,則必定要傳入A類或者其子類對象,不然將沒法調用方法
    對於Python這樣的動態語言,則不必定要傳入A類或其子類對象,只需保證傳入的對象有一個run()方法便可

  這就是動態語言的"鴨子類型",它並不要求嚴格的繼承體系,一個對象只要"看起來像鴨子,走起路來像鴨子",那它就能夠被看作是鴨子

  關於file-like object
    Python的"file-like object"就是一種鴨子類型
    真正的文件對象都有一個read()方法,但許多對象,只要有read()方法,都被視爲"file-like object"
    許多函數接收的參數就是"file-like object",不必定要傳入真正的文件對象,徹底能夠傳入任何實現了read()方法的對象blog

相關文章
相關標籤/搜索