這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
Golang的方法集繼承規則樣本
2016/11/11 · Go · Golang, IT技術
分享到:0MongoDB叢集之分區技術應用MongoDB複製集—快速搭建複製集MongoDB複製集技術內幕:工作原理及新版本改進方向MongoDB 線上講座之如何測試、調整及監控MongoDB效能本文作者: 伯樂線上 - v7 。未經作者許可,禁止轉載!
歡迎加入伯樂線上 專欄作者。
本篇通過具體樣本來展現 Golang 機制中 methods set 的繼承規則。
0x00 簡單method的規則
首先,我們聲明樣本的基本操作結構體。
更多閱讀請點擊:鄭州治療白癜風醫院
更多閱讀請點擊:鄭州治療牛皮癬醫院
Go
1
2
3
4type Cat struct{
Name string
Color string
}
我們聲明了一個 Cat 的 type,在它的基礎上我們聲明一個Meow的method:
Go
1
2
3func (c Cat) Meow() {
fmt.Println("Name:", c.Name, "Color:", c.Color)
}
在上面的代碼上, 我們聲明了一個method, 它的receiver是Cat(區別於Cat的指標),在這時,無論是我們通過 Cat類型的變數來調用method還是用 *Cat的類型來調用,Go都會正常的編譯並正常輸出,如:
,main函數中的 a 和 b 變數,一個是 Cat 類型,一個是Cat的指標類型,他們都有Meow方法。
那麼如果我們聲明的函數receiver是 *Cat呢?
1
2
3func (c *Cat) Meow() {
fmt.Println("Name:", c.Name, "Color:", c.Color)
}
在這種情況下,方法也是繼承的:
上面是簡單的 Cat 和 *Cat 上的方法集的繼承規則:
普通情況下,類型 T 和 *T 上的方法集是互相繼承的。
0x01 介面中methods set的規則
接下來我們聲明一個介面來做對比:
1
2
3
4
5
6
7
8type Meower interface{
Meow()
}
func Greet(meower Meower){
meower.Meow()
}
首先我們在Cat類型上實現Meower介面:
1
2
3func (c Cat) Meow(){
fmt.Println("Name:", c.Name, " Color:", c.Color)
}
此時編譯是沒問題的
也就是說,如果我們給Cat類型實現Meower的介面上Meow的方法,無論是Cat還是*Cat都是可以成為介面調用的。
那如果我們實現介面方式時候,選擇的receiver是*Cat呢?
1
2
3func (c *Cat) Meow(){
fmt.Println("Name:", c.Name, " Color:", c.Color)
}
編譯不通過,如:
如果給指標實現Meow方法,在第26行出現了類型錯誤,提示我們Meow方法的receiver是一個指標類型,說明此時方法不能繼承。
於是這裡的規則是:
在介面中的method,對於普通類型T:
T的methods set裡不會繼承包含*T實現的method,除非T自己實現相對應的method。
但是,*T會繼承T的method set。
0x02 嵌入類型中methods set的規則
我們討論了上面兩種情況,那考慮如果Cat作為嵌入類型(Embedded Types)時會發生什麼呢?
於是在上面的基礎上,我們來聲明這樣一個類型來做實驗:
1
2
3
4type BlackCat struct{
Cat
Age int
}
此時我們是直接可以通過BlackCat 來調用Cat實現的介面method的,
中,我們並沒有為BlackCat實現介面,僅僅為Cat實現了介面,不過BlackCat裡面嵌入了Cat的一個內部類型,也是可以通過介面調用函數Greet來調用到Meow method。
同時我們修改main函數,發現BlackCat的methods set 裡麵包含了Meow(), 如:
此時:
嵌入類型的類型中,外部類型自己未曾實現的methods被攜帶的內建函式實現時,外部類型也會將這些methods加入到自己的methods set裡。
那麼,如果外部類型BlackCat自己實現了Meow()函數(同時也實現了介面),內部和外部都實現的情況下會怎樣呢?
下面我們給BlackCat實現Meow()方法試一下:
1
2
3func (c BlackCat) Meow(){
fmt.Println("BlackName:", c.Cat.Name, " Age:", c.Age)
}
首先,編譯是沒問題的:
我們看一下a.Cat.Meow() 和 a.Meow()的運行結果:
發現BlackCat的使用了自己實現的方法,或者說它把內部Cat的Meow()方法覆蓋了。
將直接調用改成使用介面時也是如此:
兩次結果是一樣的。
0x03 結論
搞清Golang中的方法集繼承對我們寫出不囉嗦的代碼很有用處,而在Golang中,對於指標的處理也比C/C++中靈活了一些。
0x04 參考資料
Methods, Interfaces and Embedded Types in Go