python天生支持多態python
多態指的是一類事物有多種形態函數
當咱們定義一個class的時候,咱們實際上就定義了一種數據類型,咱們定義的數據類型和python自帶的數據類型,好比str、list、dict 沒什麼兩樣:spa
In [1]: class Animal: ...: pass In [2]: class Dog(Animal): ...: pass In [3]: a = list() In [4]: b = Animal() In [5]: c = Dog() In [6]: isinstance(a, list) # a 是 list 類型 Out[6]: True In [7]: isinstance(b, Animal) # b 是 Animal 類型 Out[7]: True In [8]: isinstance(c, Dog) # c 是 Dog 類型 Out[8]: True In [9]: isinstance(c, Animal) Out[9]: True
c 不單單是 Dog, c 仍是 Animal, 由於 Animal 是 c的父類,所以 c 及時 Dog類型,也是 Animal 類型,可是反過來是不行的。code
In [12]: b = Animal() In [13]: isinstance(b, Dog) Out[13]: False
Dog 能夠當作 Animal,可是 Animal 不能夠當作 Dog對象
要理解多態,須要編寫一個 run_twice 函數。blog
class Animal: def run(self): print('Animal is running...') class Dog(Animal): def run(self): print('dog is running...') class Cat(Animal): def run(self): print('cat is running...') def run_twice(animal): animal.run() animal.run() dog = Dog() run_twice(dog)
當咱們傳入 Animal 的實例時,run_twice() 就打印出:繼承
dog is running... dog is running...
如今,若是咱們再定義一個Tortoise類型,也從Animal派生:class
class Animal: def run(self): print('Animal is running...') class Dog(Animal): def run(self): print('dog is running...') class Cat(Animal): def run(self): print('cat is running...') class Tortoise(Animal): def run(self): print('tortoise is running...') def run_twice(animal): animal.run() animal.run() tortoise = Tortoise() run_twice(tortoise)
當咱們調用 run_twice()時,傳入 Tortoise 的實例:變量
tortoise is running... tortoise is running...
你會發現,新增一個Animal的子類,沒必要對run_twice()作任何修改,實際上,任何依賴Animal做爲參數的函數或者方法均可以不加修改地正常運行,緣由就在於多態。擴展
對於一個變量,咱們只須要知道它是Animal類型,無需確切地知道它的子類型,就能夠放心地調用run()方法,而具體調用的run()方法是做用在Animal、Dog、Cat仍是Tortoise對象上,由運行時該對象的確切類型決定,
這就是多態真正的威力:調用方只管調用,無論細節,而當咱們新增一種Animal的子類時,只要確保run()方法編寫正確,不用管原來的代碼是如何調用的。這就是著名的「開閉」原則:
靜態語言 vs 動態語言
對於靜態語言(例如Java)來講,若是須要傳入Animal類型,則傳入的對象必須是Animal類型或者它的子類,不然,將沒法調用run()方法。
對於Python這樣的動態語言來講,則不必定須要傳入Animal類型。咱們只須要保證傳入的對象有一個run()方法就能夠了:
class Timer: def run(self): print('Start...') def run_twice(animal): animal.run() animal.run() timer = Timer() run_twice(timer)
這就是動態語言的「鴨子類型」,它並不要求嚴格的繼承體系,一個對象只要「看起來像鴨子,走起路來像鴨子」,那麼就能夠被看作是鴨子。
小結
動態語言的鴨子類型的特色決定了繼承不像靜態語言那樣是必須的。