Go語言使用接口(interface)和結構(struct)來模擬對象繼承

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語言。編譯

相關文章
相關標籤/搜索