Go語言裏面沒有面向對象語言裏的繼承關鍵字或者語法,因此明面上是沒有繼承關係的。可是,通過面向對象愛好者的努力,仍是在Go語言上實現了模擬繼承的功能。下面舉個簡單例子來講明一下。首先,有一個Dog對象,它實現了Funny接口,從而具有了Funny接口的兩種行爲:callMyName()和getName()。而後,有一個BDog對象,它沒有實現Funny接口,但是它也想具有Funny接口的兩種行爲:callMyName()和getName(),怎麼辦呢?在面嚮對象語言裏面,最簡單的辦法就是BDog繼承Dog。這樣BDog就自動得到Funny接口的兩種能力。 那麼,對於Go語言這種沒有繼承關係的語言該如何處理呢?看看演示代碼吧。
this
package main
import "fmt"
type Dog struct {
name string
}
type BDog struct {
Dog
name string
}
type Funny interface {
callMyName()
getName() string
}
func (this *Dog) callMyName() {
fmt.Printf("my name is %q\n", this.getName())
}
func (this *Dog) getName() string {
return this.name
}
func main() {
b := new(BDog)
b.name = "this is a BDog name"
b.Dog.name = "this is a Dog name"
b.callMyName()
}代碼解讀:spa
首先,程序聲明一個Dog結構,並實現 Funny 接口。能夠把Dog看作面向對象裏的父類。code
而後,程序聲明一個BDog結構。BDog結構包含一個Dog的成員,而這個Dog成員就是BDog得到Funny 接口能力的關鍵。對象
在main方法裏面,先new一個BDog對象實例b,而後對BDog對象實例b的成員屬性分別賦值,最後,b去調用callMyName()方法。繼承
b爲何能直接調用callMyName()方法呢?由於Go編譯器在編譯檢查過程當中,會去遍歷結構中的成員,並檢查成員中是否有支持 接口
callMyName()的調用。若是隻找到一個成員支持這種調用,那麼b.callMyName()是合法的。若是是兩個或者兩個以上的成員都get
支持,那麼就會報一個調用有歧義的錯誤。編譯器
演示程序運行的結果是:my name is "this is a Dog name" 。 這結果就好像BDog繼承了Dog同樣,funny。string
經過接口和結構的搭配使用,Go語言模擬單繼承和多繼承是很方便的事情。簡單的語言, 強大的表達能力,這就是Go語言。編譯