(三)多型與多型性
阿新 • • 發佈:2020-07-19
一、多型
多型指的是一類事物有多種形態
動物有多種形態:人,狗,豬
import abc class Animal(metaclass=abc.ABCMeta): # 同一類事物:動物 @abc.abstractmethod def talk(self): # 抽象方法不用實現 pass class People(Animal): # 動物的形態之一:人 def talk(self): print('say hello') class Dog(Animal): # 動物的形態之二:狗 def talk(self):print('say wangwang') class Pig(Animal): # 動物的形態之三:豬 def talk(self): print('say hengheng')
檔案有多種形態:文字檔案,可執行檔案。
import abc class File(metaclass=abc.ABCMeta): # 同一類事物:檔案 @abc.abstractmethod def click(self): pass class Text(File): # 檔案的形態之一:文字檔案 def click(self):print('open file') class ExeFile(File): # 檔案的形態之二:可執行檔案 def click(self): print('execute file')
二、多型性
1,什麼是多型動態繫結(在繼承的背景下使用時,有時也稱為多型性)
多型性是指在不考慮例項型別的情況下使用例項
詳解:
在面向物件方法中一般是這樣表述多型性:向不同的物件傳送同一條訊息 (!!!obj.func():是呼叫了obj的方法func,又稱為向obj傳送了一條訊息func), 不同的物件在接收時會產生不同的行為(即方法)。 也就是說,每個物件可以用自己的方式去響應共同的訊息。 所謂訊息,就是呼叫函式,不同的行為就是指不同的實現,即執行不同的函式。 比如:老師.下課鈴響了(),學生.下課鈴響了(), 老師執行的是下班操作,學生執行的是放學操作, 雖然二者訊息一樣,但是執行的效果不同
多型性分為靜態多型性和動態多型性。
靜態多型性:如任何型別都可以用運算子+進行運算
動態多型性:如下
import abc class Animal(metaclass=abc.ABCMeta): # 同一類事物:動物 @abc.abstractmethod def talk(self): # 抽象方法不用實現 pass class People(Animal): # 動物的形態之一:人 def talk(self): print('say hello') class Dog(Animal): # 動物的形態之二:狗 def talk(self): print('say wangwang') class Pig(Animal): # 動物的形態之三:豬 def talk(self): print('say hengheng') peo = People() dog = Dog() pig = Pig() # peo、dog、pig都是動物,只要是動物肯定有talk方法 # 於是我們可以不用考慮它們三者的具體是什麼型別,而直接使用 # peo.talk() # dog.talk() # pig.talk() """ say hello say wangwang say hengheng """ # 更進一步,我們可以定義一個統一的介面來使用 def func(obj): obj.talk() func(peo) func(dog) func(pig) """ 實現的效果是一樣的 say hello say wangwang say hengheng """動態多型性
2,為什麼要用多型性(多型性的好處)
其實從上面多型性的例子可以看出,我們並沒有增加什麼新的知識,也就是說 python 本身就是支援多型性的,這麼做的好處是什麼呢?
1)增加了程式的靈活性
以不變應萬變,不論物件千變萬化,使用者都是同一種形式去呼叫,如:func(animal)
2)增加了程式的可擴充套件性
通過繼承 animal 類建立了一個新的類,使用者無需更改自己的程式碼,還是用 func(animal) 去呼叫
import abc class Animal(metaclass=abc.ABCMeta): # 同一類事物:動物 @abc.abstractmethod def talk(self): pass class Cat(Animal): # 屬於動物的另外一種形態:貓 def talk(self): print('say miao') def func(animal): # 對於使用者來說,自己的程式碼根本無需改動 animal.talk() cat1 = Cat() # 例項出一隻貓 func(cat1) # 甚至連呼叫方式也無需改變,就能呼叫貓的talk功能 # say miao ''' 這樣我們新增了一個形態Cat,由Cat類產生的例項cat1,使用者可以在完全不需要修改自己程式碼的情況下。 使用和人、狗、豬一樣的方式呼叫cat1的talk方法,即func(cat1) '''View Code
3,鴨子型別
Python 崇尚鴨子型別,即‘如果看起來像、叫聲像而且走起路來像鴨子,那麼它就是鴨子’
python 程式設計師通常根據這種行為來編寫程式。例如,如果想編寫現有物件的自定義版本,可以繼承該物件,也可以建立一個外觀和行為像,但與它無任何關係的全新物件,後者通常用於儲存程式元件的鬆耦合度。
例1:利用標準庫中定義的各種“與檔案類似”的物件,儘管這些物件的工作方式像檔案,但他們沒有繼承內建檔案物件的方法。
# 二者都像鴨子,二者看起來都像檔案,因而就可以當檔案一樣去用 class TxtFile: def read(self): pass def write(self): pass class DiskFile: def read(self): pass def write(self): passView Code
例2:其實大家一直在享受著多型性帶來的好處,比如 Python 的序列型別有多種形態:字串,列表,元組,多型性體現如下:
# str,list,tuple都是序列型別,可算長度。 s = str('hello') l = list([1,2,3]) t = tuple((4,5,6)) # 我們可以在不考慮三者型別的前提下使用s,l,t s.__len__() l.__len__() t.__len__() len(s) len(l) len(t)View Code