1. 程式人生 > >面向物件【林老師版】:多型與多型性(十三)

面向物件【林老師版】:多型與多型性(十三)

一、多型

多型指的是一類事物有多種形態,比如

1、動物有多種形態:人,狗,豬

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 aoao')

2、檔案有多種形態:文字檔案,可執行檔案

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、什麼是多型動態繫結(在繼承的背景下使用時,有時也稱為多型性)

多型性是指在不考慮例項型別的情況下使用例項,多型性分為靜態多型性和動態多型性

靜態多型性:如任何型別都可以用運算子+進行運算

動態多型性:如下

peo=People()
dog=Dog()
pig=Pig()

#peo、dog、pig都是動物,只要是動物肯定有talk方法
#於是我們可以不用考慮它們三者的具體是什麼型別,而直接使用
peo.talk()
dog.talk()
pig.talk()

#更進一步,我們可以定義一個統一的介面來使用
def func(obj):
    obj.talk()

2、為什麼要用多型性(多型性的好處)

其實大家從上面多型性的例子可以看出,我們並沒有增加什麼新的知識,也就是說python本身就是支援多型性的,這麼做的好處是什麼呢?

1.增加了程式的靈活性

  以不變應萬變,不論物件千變萬化,使用者都是同一種形式去呼叫,如func(animal)

2.增加了程式額可擴充套件性

 通過繼承animal類建立了一個新的類,使用者無需更改自己的程式碼,還是用func(animal)去呼叫 

 

>>> 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)
'''

三、鴨子型別

逗比時刻:

Python崇尚鴨子型別,即‘如果看起來像、叫聲像而且走起路來像鴨子,那麼它就是鴨子’

python程式設計師通常根據這種行為來編寫程式。例如,如果想編寫現有物件的自定義版本,可以繼承該物件

也可以建立一個外觀和行為像,但與它無任何關係的全新物件,後者通常用於儲存程式元件的鬆耦合度。

例1:利用標準庫中定義的各種‘與檔案類似’的物件,儘管這些物件的工作方式像檔案,但他們沒有繼承內建檔案物件的方法

#二者都像鴨子,二者看起來都像檔案,因而就可以當檔案一樣去用
class TxtFile:
    def read(self):
        pass

    def write(self):
        pass

class DiskFile:
    def read(self):
        pass
    def write(self):
        pass

例2:序列型別有多種形態:字串,列表,元組,但他們直接沒有直接的繼承關係

#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)