摘要:許多編程語(yǔ)言都支持,通常是動(dòng)態(tài)編程語(yǔ)言用來實(shí)現(xiàn)多態(tài)的一種方式。在編程中,也常常用這種方式來描述事物。那么不同的編程語(yǔ)言中,是怎么樣實(shí)現(xiàn)的呢中的先看一個(gè)函數(shù)有一個(gè)函數(shù),傳過來一個(gè)參數(shù),是可以獲取一個(gè)鏈接的資源的。
如果一只動(dòng)物走起來像鴨子、游泳起來像鴨子、叫起來也像鴨子,那么這只動(dòng)物就可以被稱為鴨子。
許多編程語(yǔ)言都支持 Duck Typing ,通常 Duck Typing 是動(dòng)態(tài)編程語(yǔ)言用來實(shí)現(xiàn)多態(tài)的一種方式。
在理解 Duck Typing 前,先看一張圖片,這是曾經(jīng)一度很火的大黃鴨
先問一個(gè)比較考三觀的問題:圖片中的大黃鴨,它是不是一只鴨子呢?
這個(gè)問題,得看你從哪個(gè)角度去看,如果從人們常識(shí)的認(rèn)知中的角度去看,它顯然不是一只鴨子,因?yàn)樗B最基本的生命都沒有。
但是從 Duck Typing 的角度來看,它就是一只鴨子!
Duck Typing 的原話是,走起來像鴨子、游泳起來像鴨子、叫起來也像鴨子,那么它就是一只鴨子。
這個(gè)原話是可以靈活理解的,就看我們?cè)趺炊x鴨子的行為,我們可以說,能浮在水上游的,黃色的,可愛的就是鴨子,那么,圖片中的大黃鴨,它就是一只鴨子!
這就是所謂的 Duck Typing,它只關(guān)心事物的外部行為而非內(nèi)部結(jié)構(gòu)。它并不關(guān)心你這只鴨子是長(zhǎng)肉的還是充氣的。
在編程中,也常常用這種方式來描述事物。那么不同的編程語(yǔ)言中,Duck Typing 是怎么樣實(shí)現(xiàn)的呢?
1. Python 中的 Duck Typing
先看一個(gè)函數(shù):
def download(fetcher): return fetcher.get("http://xxx");
有一個(gè) download 函數(shù),傳過來一個(gè) fetcher 參數(shù),fetcher 是可以獲取一個(gè) url 鏈接的資源的。
這個(gè) fetcher 就是一個(gè) Duck Typing 的對(duì)象,使用者約定好這個(gè) fetcher 會(huì)有一個(gè) get 函數(shù)就可以了。
顯然這個(gè) download 函數(shù)會(huì)有以下問題:
運(yùn)行時(shí)才知道傳入的 fetcher 有沒有 get 函數(shù)。那么站在 download 函數(shù)的使用者的角度上看,我怎么知道需要給 fetcher 實(shí)現(xiàn) get 方法呢?我不可能去閱讀 download 函數(shù)的代碼,實(shí)際情況中,可能 download 函數(shù)的代碼很長(zhǎng),可能 fetcher 不只要實(shí)現(xiàn) get 方法,還有其它方法需要實(shí)現(xiàn)。通常這種情況需要通過加注釋來說明。
2. C++ 中的 Duck Typing
C++ 不是動(dòng)態(tài)語(yǔ)言,但是它也能支持 Duck Typing,它是通過模板來支持的。
示例代碼:
templatestring download(const F& fetcher){ return fetcher.get("http://xxxx") }
這段代碼與 Python 的實(shí)現(xiàn)方法類似,這個(gè) fetcher 隨便什么類型都可以,只要實(shí)現(xiàn)一個(gè) get 方法,就能通過編譯。
那么這種實(shí)現(xiàn)方法有什么缺點(diǎn)呢,就是,編譯時(shí),才知道傳入的 fetcher 有沒有 get 方法。
但它比 python 好一點(diǎn)了,python 是運(yùn)行時(shí)才知道,C++ 是編譯時(shí)就知道。
同樣,這種情況,還是需要注釋來說明。
3. Java 中的類似代碼
Java 沒有 Duck Typing,它只有類似的代碼。Java 的 duck typing :
String download(F fetcher){ return fetcher.get("http://xxxx") }
它同樣也用了模板類型。模板 F 必須 extends FetcherInterface ,有了這個(gè)限定,就能逼著 download 函數(shù)的使用者對(duì) fetcher 實(shí)現(xiàn) get 方法,它解決了需要注釋來說明的缺點(diǎn)。
傳入的參數(shù)必須實(shí)現(xiàn) FetcherInterface 接口,就沒有運(yùn)行時(shí)發(fā)現(xiàn)錯(cuò)誤,編譯時(shí)發(fā)現(xiàn)錯(cuò)誤的問題。
但是,它嚴(yán)格上來說不是 Duck Typing 。
如果 download 函數(shù)只依賴 fetcher 的 get 方法,而 FetcherInterface 接口必須要實(shí)現(xiàn)除 get 方法以外,還有其它方法,那么也要一一實(shí)現(xiàn),非常不靈活。
4. Go 中的 Duck Typing
在 Java 的 Duck Typing 類似代碼中,如果 fetcher 參數(shù)需要同時(shí)實(shí)現(xiàn)兩個(gè)或以上的接口方法時(shí),Java 是沒有辦法做到的。但 Go 語(yǔ)言可以做到。
type Fetcher interface { Get(url string) string } type Saver interface { Save(content string) } type FetcherAndSaver interface { Fetcher Saver } func download(f Fetcher) string { return f.Get("http://xxxx") } func save(f saver) { f.Save("some thing") } func downloadAndSave(f FetcherAndSaver) { content := f.Get("http://xxxx") f.Save(content) } # 實(shí)現(xiàn)者 type MyFetcherAndSaver struct { } func (f MyFetcherAndSaver) Get(url string) string { ... } func (f MyFetcherAndSaver) Save(content string) { ... } func main() { f := MyFetcherAndSaver{} download(f) save(f) downloadAndSave(f) }
這里定義了三個(gè)接口,只要有 Get 方法的就是 Fetcher,只要有 Save 方法的就是 Saver,同時(shí)有 Get 方法和 Save 方法就是 FetcherAndSaver 。
實(shí)現(xiàn)者 MyFetcherAndSaver 并不需要聲明它實(shí)現(xiàn)了哪些接口,只要它有相關(guān)接口的所定義的方法,那么它的實(shí)例,就即能作為 Fetcher 接口來使用,又能作為 Saver 接口來使用,也能作為 FetcherAndSaver 接口來使用。
Go 的實(shí)現(xiàn)方法相對(duì)比較靈活,又不失類型檢查??偟膩碚f,特點(diǎn)有:
即能同時(shí)實(shí)現(xiàn)多個(gè)接口
又具有 python , C++ 的 Duck Typing 靈活性
又具有 java 的類型檢查。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/44160.html
摘要:許多編程語(yǔ)言都支持,通常是動(dòng)態(tài)編程語(yǔ)言用來實(shí)現(xiàn)多態(tài)的一種方式。在編程中,也常常用這種方式來描述事物。那么不同的編程語(yǔ)言中,是怎么樣實(shí)現(xiàn)的呢中的先看一個(gè)函數(shù)有一個(gè)函數(shù),傳過來一個(gè)參數(shù),是可以獲取一個(gè)鏈接的資源的。 如果一只動(dòng)物走起來像鴨子、游泳起來像鴨子、叫起來也像鴨子,那么這只動(dòng)物就可以被稱為鴨子。 許多編程語(yǔ)言都支持 Duck Typing ,通常 Duck Typing 是動(dòng)態(tài)編程...
摘要:有一些定制類的特殊方法,如,其中一些具有動(dòng)態(tài)特性的方法可以用來很方便地處理某些動(dòng)態(tài)狀況。動(dòng)態(tài)化屬性和方法的調(diào)用,當(dāng)調(diào)用不存在的屬性時(shí),如果存在方法,就會(huì)調(diào)用方法來嘗試獲得屬性。這種完全動(dòng)態(tài)的調(diào)用可以應(yīng)對(duì)一些動(dòng)態(tài)情況,例如實(shí)現(xiàn)。 Python有一些定制類的特殊方法,如__str__()、__iter__()、__getitem__(),其中一些具有動(dòng)態(tài)特性的方法可以用來很方便地處理某些動(dòng)...
摘要:本文已收錄修煉內(nèi)功躍遷之路我們寫的方法在被編譯為文件后是如何被虛擬機(jī)執(zhí)行的對(duì)于重寫或者重載的方法,是在編譯階段就確定具體方法的么如果不是,虛擬機(jī)在運(yùn)行時(shí)又是如何確定具體方法的方法調(diào)用不等于方法執(zhí)行,一切方法調(diào)用在文件中都只是常量池中的符號(hào)引 本文已收錄【修煉內(nèi)功】躍遷之路 showImg(https://segmentfault.com/img/bVbuesq?w=2114&h=12...
摘要:類型檢測(cè)在中提供兩種檢測(cè)類型的方法,但是它們并不總是靠譜。引用類型引用類型使用檢測(cè),返回都是。這個(gè)時(shí)候可以用,它的語(yǔ)法是實(shí)例對(duì)象構(gòu)造函數(shù)不僅能檢測(cè)構(gòu)造對(duì)象的構(gòu)造器,還檢測(cè)原型鏈。 類型檢測(cè) 在js中提供兩種檢測(cè)類型的方法,但是它們并不總是靠譜。 typeof instanceof 下面我們來看看各個(gè)類型的應(yīng)該如何進(jìn)行檢測(cè)比較靠譜 1. 基本類型 基本類型(除null之外)的檢測(cè)使用...
摘要:本文重點(diǎn)協(xié)議是中非正式的接口了解抽象基類的基本概念以及標(biāo)準(zhǔn)庫(kù)中的抽象基類掌握抽象基類的使用方法。三抽象基類的使用通過繼承聲明抽象基類聲明抽象基類最簡(jiǎn)單的方式是繼承或其他抽象基類注意在之間,繼承抽象基類的語(yǔ)法是。 導(dǎo)語(yǔ):本文章記錄了本人在學(xué)習(xí)Python基礎(chǔ)之面向?qū)ο笃闹攸c(diǎn)知識(shí)及個(gè)人心得,打算入門Python的朋友們可以來一起學(xué)習(xí)并交流。 本文重點(diǎn): 1、協(xié)議是Python中非正式的接...
閱讀 2109·2023-04-26 01:33
閱讀 1727·2023-04-26 00:52
閱讀 1122·2021-11-18 13:14
閱讀 5860·2021-09-26 10:18
閱讀 2975·2021-09-22 15:52
閱讀 1558·2019-08-29 17:15
閱讀 3085·2019-08-29 16:11
閱讀 1089·2019-08-29 16:11