《Go語言實戰(zhàn)》讀書筆記险绘,未完待續(xù),歡迎掃碼關(guān)注公眾號
flysnow_org
椎椰,第一時間看后續(xù)筆記。
嵌入類型沾鳄,或者嵌套類型俭识,這是一種可以把已有的類型聲明在新的類型里的一種方式,這種功能對代碼復(fù)用非常重要洞渔。
在其他語言中茫藏,有繼承可以做同樣的事情柏蘑,但是在Go語言中白华,沒有繼承的概念杏糙,Go提倡的代碼復(fù)用的方式是組合,所以這也是嵌入類型的意義所在浆熔,組合而不是繼承本辐,所以Go才會更靈活。
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
type Closer interface {
Close() error
}
type ReadWriter interface {
Reader
Writer
}
type ReadCloser interface {
Reader
Closer
}
type WriteCloser interface {
Writer
Closer
}
以上是標準庫io
包里医增,我們常用的接口慎皱,可以看到ReadWriter
接口是嵌入Reader
和Reader
接口而組合成的新接口,這樣我們就不用重復(fù)的定義被嵌入接口里的方法叶骨,直接通過嵌入就可以了茫多。嵌入類型同樣適用于結(jié)構(gòu)體類型,我們再來看個例子:
type user struct {
name string
email string
}
type admin struct {
user
level string
}
嵌入后忽刽,被嵌入的類型稱之為內(nèi)部類型天揖、新定義的類型稱之為外部類型,這里user
就是內(nèi)部類型跪帝,而admin
是外部類型今膊。
通過嵌入類型,與內(nèi)部類型相關(guān)聯(lián)的所有字段伞剑、方法斑唬、標志符等等所有,都會被外包類型所擁有黎泣,就像外部類型自己的一樣恕刘,這就達到了代碼快捷復(fù)用組合的目的,而且定義非常簡單聘裁,只需聲明這個類型的名字就可以了雪营。
同時弓千,外部類型還可以添加自己的方法衡便、字段屬性等,可以很方便的擴展外部類型的功能。
func main() {
ad:=admin{user{"張三","zhangsan@flysnow.org"},"管理員"}
fmt.Println("可以直接調(diào)用,名字為:",ad.name)
fmt.Println("也可以通過內(nèi)部類型調(diào)用,名字為:",ad.user.name)
fmt.Println("但是新增加的屬性只能直接調(diào)用镣陕,級別為:",ad.level)
}
以上是嵌入類型的使用谴餐,可以看到,我們在初始化的時候呆抑,采用的是字面值的方式岂嗓,所以要按其定義的結(jié)構(gòu)進行初始化,先初始化user
這個內(nèi)部類型的鹊碍,再初始化新增的level
屬性厌殉。
對于內(nèi)部類型的屬性和方法訪問上,我們可以用外部類型直接訪問侈咕,也可以通過內(nèi)部類型進行訪問公罕;但是我們?yōu)橥獠款愋托略龅姆椒▽傩宰侄危荒苁褂猛獠款愋驮L問耀销,因為內(nèi)部類型沒有這些楼眷。
當然,外部類型也可以聲明同名的字段或者方法熊尉,來覆蓋內(nèi)部類型的罐柳,這種情況方法比較多,我們以方法為例
func main() {
ad:=admin{user{"張三","zhangsan@flysnow.org"},"管理員"}
ad.user.sayHello()
ad.sayHello()
}
type user struct {
name string
email string
}
type admin struct {
user
level string
}
func (u user) sayHello(){
fmt.Println("Hello狰住,i am a user")
}
func (a admin) sayHello(){
fmt.Println("Hello张吉,i am a admin")
}
內(nèi)部類型user
有一個sayHello
方法,外部類型對其進行了覆蓋催植,同名重寫sayHello
芦拿,然后我們在main方法里分別訪問這兩個類型的方法,打印輸出:
Hello查邢,i am a user
Hello蔗崎,i am a admin
從輸出中看,方法sayHello
被成功覆蓋了扰藕。
嵌入類型的強大缓苛,還體現(xiàn)在:如果內(nèi)部類型實現(xiàn)了某個接口,那么外部類型也被認為實現(xiàn)了這個接口邓深。我們稍微改造下例子看下未桥。
func main() {
ad:=admin{user{"張三","zhangsan@flysnow.org"},"管理員"}
sayHello(ad.user)//使用user作為參數(shù)
sayHello(ad)//使用admin作為參數(shù)
}
type Hello interface {
hello()
}
func (u user) hello(){
fmt.Println("Hello,i am a user")
}
func sayHello(h Hello){
h.hello()
}
這個例子原來的結(jié)構(gòu)體類型user
和admin
的定義不變芥备,新增了一個接口Hello
,然后讓user
類型實現(xiàn)這個接口冬耿,最后我們定義了一個sayHello
方法,它接受一個Hello
接口類型的參數(shù)萌壳,最終我們在main函數(shù)演示的時候亦镶,發(fā)現(xiàn)不管是user
類型日月,還是admin
類型作為參數(shù)傳遞給sayHello
方法的時候,都可以正常調(diào)用缤骨。
這里就可以說明admin
實現(xiàn)了接口Hello
,但是我們又沒有顯示的聲明類型admin
實現(xiàn)爱咬,所以這個實現(xiàn)是通過內(nèi)部類型user
實現(xiàn)的,因為admin
包含了user
所有的方法函數(shù)绊起,所以也就實現(xiàn)了接口Hello
精拟。
當然外部類型也可以重新實現(xiàn),只需要像上面例子一樣覆蓋同名的方法即可虱歪。這里要說明的是蜂绎,不管我們?nèi)绾瓮采w,都不會影響內(nèi)部類型笋鄙,我們還可以通過訪問內(nèi)部類型來訪問它的方法荡碾、屬性字段等。
嵌入類型的定義局装,是Go為了方便我們擴展或者修改已有類型的行為坛吁,是為了宣傳組合這個概念而設(shè)計的,所以我們經(jīng)常使用組合铐尚,靈活運用組合拨脉,擴展出更多的我們需要的類型結(jié)構(gòu)。
《Go語言實戰(zhàn)》讀書筆記宣增,未完待續(xù)玫膀,歡迎掃碼關(guān)注公眾號
flysnow_org
,第一時間看后續(xù)筆記爹脾。