golang中interface的一些語法缺陷的改進

GO語言有一個獨門祕技:interface,是大師們對OOP的經典詮釋,是對傳統OOP思維的一個巧妙顛覆。

既優雅地實現運行時多態,又不需要像C++那樣顯式申明,完美的解除了類型實現跟接口調用之間的耦合。

Go語言的主要設計者之一Russ Cos曾經說過,如果只能選擇一個Go語言的特性移植到其他語言中,他會選擇接口。可見接口在GO中的地位,及其對GO這門語言所帶來的活力。

Russ Cos: interface https://research.swtch.com/interfaces

Ian Lance Taylor: go interface https://www.airs.com/blog/archives/277

 

然而,由於GO的interface定義與具體實現類型之間不需要顯式申明,只需要實現類實現interface定義的所有method即可賦值。

然而這種寬鬆的約定,卻帶來一些邏輯上的麻煩。

這裏有個例子:https://github.com/vipally/glab/blob/master/lab12/walk_test.go

 

有兩個包filepath和pet都定義了一個Walker接口,並實現了相應的實現類型。

但是巧的是這兩個Walker接口的定義都是一樣的

type Walker interface {
    Walk()
}

 

但是顯然,pet.Walker是想實現所有pet的“走路”行爲

而filepath.Walker是想實現目錄的“遍歷”功能

然而,雖然兩個接口的定義是一樣的,但是期望的行爲應該是不一樣的。

從邏輯上說,用filepath.Walker調用pet.Dog.Walk()應該是一個錯誤的行爲,然而從GO的語法上看,這種操作居然是合法的:

	
var petWalker pet.Walker
var filepathWalker filepath.Walker
println("call by pet.Walker:")
petWalker = &pet.Dog{}
petWalker.Walk()
petWalker = &pet.Cat{}
petWalker.Walk()
petWalker = &filepath.FilePath{}
petWalker.Walk()

println("\ncall by filepath.Walker:")
filepathWalker = &pet.Dog{}
filepathWalker.Walk()
filepathWalker = &pet.Cat{}
filepathWalker.Walk()
filepathWalker = &filepath.FilePath{}
filepathWalker.Walk()

println("\nThe strange is that pet.Warker and filepath.Walker has the same signiture but they are not the same one.")
println("But Go treat them as the same one.")


 

從語法上修復這個bug的方法如下:

implements pet.Walker{
    *pet.Dog
    *pet.Cat
}

implements *filepath.FilePath{
    filepath.Walker
    filepath.Reader
}

通過顯式的申明 實現並可以使用接口的具體類型,告訴編譯器什麼樣的接口賦值,是被允許的。

這種外部申明的語法,仍然沒有破壞GO interface非侵入式的設計,無須對interface和實現類型做任何修改。

這樣,下面的接口賦值將被編譯器判斷爲非法

filepathWalker  = &pet.Dog{}

 

另外,這種顯式申明還有一個好處,就是可以明確通過查找引用的方法,找出實現了某個接口的所有實現類型。

起到一個建立接口定義與實現類型關係的書面說明,

不會像現在一樣,通過interface名字,只能找到interface的對象,卻沒法找出所有實現並賦值給該接口的所有具體類型的信息。

 

參考鏈接:

Russ Coss: interface https://research.swtch.com/interfaces

Ian Lance Taylor: go interface https://www.airs.com/blog/archives/277

confused interface: https://github.com/vipally/glab/blob/master/lab12/walk_test.go

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章