类的多态
#我們前面了解了繼承,繼承可以幫助我們重復使用代碼。但對于繼承中的示例,無論是Dog還是Cat,調用父類的run()方法時顯示的都是Animal is running.,如果想讓結果顯示為Dog is running.和Cat is running.,該如果處理呢? #我們對Dog和Cat做如下改進: 1 #! /usr/bin/python3
2 #-*-coding:UTF-8-*-
3 #clas_多態
4
5 class Animal(object):
6 def run(self):
7 print('Animal is running.')
8
9 class Dog(Animal):
10 def run(self):
11 print('Dog is running.')
12
13 class Cat(Animal):
14 def run(self):
15 print('Cat is running.') #執行如下語句: 1 dog=Dog()
2 print('實例化Dog類')
3 dog.run()
4
5 cat=Cat()
6 print('實例化Cat類')
7 cat.run() #程序執行結果如下: 1 D:\Python\workspace\datatime\20171129>python class_多態.py
2 實例化Dog類
3 Dog is running.
4 實例化Cat類
5 Cat is running. #由執行結果看到,分別得到了Dog和Cat各自的running結果。 #當子類和父類存在相同的run()方法時,子類的run()方法會覆蓋父類的run()方法,在代碼運行時總會調用子類的run()方法,稱之為多態。 #多態來自于希臘語,意思是有多種形式。多態意味著即使不知道變量所引用的對象類型是什么,也能對對象進行操作,多態會根據對象(或類)的不同而表現出不同的行為。例如,我們在上面的Animal類中定義了run方法,Dog和Cat分別繼承Animal類,并且分別定義了自己的run方法,最后Dog和Cat調用的還是自己定義的run方法。 #為了更好了解什么是多態,我們對數據類型再做一個說明。當我們定義一個類時,實際上就是定義了一種數據類型。定義的數據類型和Python自帶的數據類型(如str、list、dict)沒什么區別。 1 #! /usr/bin/python3
2 #-*-coding:UTF-8-*-
3 #clas_多態
4
5 class Animal(object):
6 def run(self):
7 print('Animal is running.')
8
9 class Dog(Animal):
10 pass
11
12 a=list() #a是list類型
13 b=Animal() #b是Animal類型
14 c=Dog() #c是Dog類型 #下面用isinstance()方法判斷一個變量是否是某個類型。 1 print('a是否是list類型:',isinstance(a,list))
2 print('b是否是Animal類型:',isinstance(b,Animal))
3 print('c是否是Dog類型:',isinstance(c,Dog)) #執行結果如下: 1 D:\Python\workspace\datatime\20171129>python class_多態.py
2 a是否是list類型: True
3 b是否是Animal類型: True
4 c是否是Dog類型: True #由執行結果看到,a,b,c確實分別為list、Animal、Dog三種類型。我們再執行如下語句: 1 print('c是否是Dog類型:',isinstance(c,Dog))
2 print('c是否是Animal類型:',isinstance(c,Animal)) #執行結果如下: 1 c是否是Dog類型: True
2 c是否是Animal類型: True #由執行結果看到,c既是Dog類型又是Animal類型,這怎么理解呢? #因為Dog是從Animal繼承下來的,當我們創建Dog的實例c時,我們認為c的數據類型是Dog,但c同時也是Animal,Dog本來就是Animal的一種。 #在繼承關系中,如果一個實例的數據類型是某個子類,那它的數據類型也可以看作是父類。但反過來就不行,例如如下語句: 1 print('b是否是Dog類型:',isinstance(b,Dog)) #執行結果如下: 1 b是否是Dog類型: False #由輸出結果看到,變量b是Animal的實例化對象,是Animal類型,但不是Dog類型,也就是Dog可以看成Animal,但Animal不可以看成Dog。 #我們再看一個示例。編寫一個函數,這個函數接收一個Animal類型的變量,定義并執行如下函數,執行時傳入Animal的實例: 1 #! /usr/bin/python3
2 #-*-coding:UTF-8-*-
3 #class_多態_2
4
5 class Animal(object):
6 def run(self):
7 print('Animal is running.')
8
9 def run_two_times(animal):
10 animal.run()
11 animal.run()
12
13 run_two_times(Animal()) #執行結果如下: 1 D:\Python\workspace\datatime\20171129>python class_多態_2.py
2 Animal is running.
3 Animal is running. #若執行函數傳入Dog的實例,操作如下: 1 #! /usr/bin/python3
2 #-*-coding:UTF-8-*-
3 #class_多態_2
4
5 class Animal(object):
6 def run(self):
7 print('Animal is running.')
8
9 class Dog(Animal):
10 def run(slef):
11 print('Dog is running.')
12
13 def run_two_times(animal):
14 animal.run()
15 animal.run()
16
17 run_two_times(Dog()) #得到的執行結果如下: 1 D:\Python\workspace\datatime\20171129>python class_多態_2.py
2 Dog is running.
3 Dog is running. #若傳入Cat的實例,操作如下: 1 #! /usr/bin/python3
2 #-*-coding:UTF-8-*-
3 #class_多態_2
4
5 class Animal(object):
6 def run(self):
7 print('Animal is running.')
8
9 class Dog(Animal):
10 def run(slef):
11 print('Dog is running.')
12
13 class Cat(Animal):
14 def run(self):
15 print('Cat is running.')
16
17 def run_two_times(animal):
18 animal.run()
19 animal.run()
20
21 run_two_times(Animal())
22 run_two_times(Dog())
23 run_two_times(Cat()) #得到執行結果如下: 1 D:\Python\workspace\datatime\20171129>python class_多態_2.py
2 Animal is running.
3 Animal is running.
4 Dog is running.
5 Dog is running.
6 Cat is running.
7 Cat is running. #看上去沒有什么特殊的地方,已經正確輸出預期結果了,但仔細想想看,如果再定義一個Bird類型,也繼承Animal類,定義如下: 1 #! /usr/bin/python3
2 #-*-coding:UTF-8-*-
3 #class_多態_2
4
5 class Animal(object):
6 def run(self):
7 print('Animal is running.')
8
9 class Dog(Animal):
10 def run(slef):
11 print('Dog is running.')
12
13 class Cat(Animal):
14 def run(self):
15 print('Cat is running.')
16
17 class Bird(Animal):
18 def run(self):
19 print('Bird if flying the sky.')
20
21 def run_two_times(animal):
22 animal.run()
23 animal.run()
24
25 run_two_times(Animal())
26 run_two_times(Dog())
27 run_two_times(Cat())
28 run_two_times(Bird()) #程序執行結果如下: 1 D:\Python\workspace\datatime\20171129>python class_多態_2.py
2 Animal is running.
3 Animal is running.
4 Dog is running.
5 Dog is running.
6 Cat is running.
7 Cat is running.
8 Bird if flying the sky.
9 Bird if flying the sky. #由執行結果看到,新增的Animal子類不必對run_two_times()方法做任何修改。實際上,任何依賴Animal作為參數的函數或方法都可以不加修改地正常運行,原因就在于多態。 #多態的好處是:當我們需要傳入Dog、Cat、Bird等對象時,只需要接收Animal類型就可以了,因為Dog、Cat、Bird等都是Animal類型,按照Animal類型進行操作即可。由于Animal類型有run()方法,因此傳入的類型只要是Animal類或繼承自Animal類,都會自動調用實際類型的run()方法。 #多態的意思是:對于一個變量,我們只需要知道它是Animal類型,無需確切知道它的子類型,就可以放心調用run()方法。具體調用的run()方法作用于Anial、Dog、Cat或Bird對象,由運行該對象的確切類型決定。 #多態真正的威力在于:調用方只管調用,不管細節。當我們新增一種Animal的子類時,只要確保run()方法編寫正確即可,不用管原來的代碼如何調用的,這就是著名的“開閉”原則:對于擴展開放,允許新增Animal子類;對于修改封閉,不需要修改依賴Animal類型的run_two_times()等函數。 #很多函數和運算符都是多態的,也許你寫的程序也可能時,即使你并非有意這樣的。只要使用多態函數和運算符,多態就會消除。唯一能夠毀掉多態的是使用函數顯式地檢查類型,如type、isinstance函數等,如果有可能,就盡量避免使用這些會毀掉多態的方式,重要的是如何讓對象按照我們希望的方式工作,無論它是否是正確類型或類。
轉載于:https://www.cnblogs.com/DLHe/p/7927394.html
總結
- 上一篇: 阿里代码规范插件 中文使用手册 FOR
- 下一篇: PHP 使用POST 获取不到部分数据问