嵌入型別
在go語言中,嵌入型別表示,在一個自定義型別中可以嵌入另一種型別。而被嵌入的型別自動擁有嵌入型別實現的介面方法以及屬性。其實,這就是go語言中繼承的實現機制。
(繼承)屬性
package main
import (
"fmt"
)
type user struct{
name string
age int
}
type admin struct{
user //嵌入user型別
level int
}
func main(){
//初始化一個admin型別的物件
ad := admin{
user:user{
name:"zhongzhong",
age:25,
},
level:1,
}
//可以直接訪問嵌入型別的屬性
fmt.Println(ad.name)
fmt.Println("mian函式執行完成")
}
//zhongzhong
//mian函式執行完成
複製程式碼
上面的程式碼中定義了兩個型別,user和admin。在admiin中嵌入了user型別。注意,嵌入型別只需要宣告型別就可以了。 在上面的程式碼中,我們把admin稱為外部型別,user稱為內部型別。
(繼承)方法
除了上面的內部型別的屬性自動提升到外部型別之外,內部型別實現的介面,也會提升到外部型別。看下面的程式碼:
package main
import (
"fmt"
)
type Speaker interface{
speak(content string)
}
type user struct{
name string
age int
}
//使用user型別的值作為接收者實現Speaker介面
func (u user) speak(content string){
fmt.Println(u.name,":",content)
}
type admin struct{
user //嵌入user型別
level int
}
func main(){
//初始化一個admin型別的物件
ad := admin{
user:user{
name:"zhongzhong",
age:25,
},
level:1,
}
//使用內部型別呼叫
ad.user.speak("你好啊")
//直接使用外部型別呼叫
ad.speak("你好")
fmt.Println("mian函式執行完成")
}
//zhongzhong : 你好啊
//zhongzhong : 你好
//mian函式執行完成
複製程式碼
上面的程式碼,既可以使用admin物件來呼叫speak方法也可以使用admin物件的嵌入型別的user物件來呼叫speak。這就表示,在外部型別中,可以直接使用內部型別的方法。
覆蓋方法(重寫)
從上面可以看出,外部型別可以直接使用內部型別的方法,那麼如果我不想使用內部型別的方法怎麼辦呢?看下面的程式碼:
package main
import (
"fmt"
)
type Speaker interface{
speak(content string)
}
type user struct{
name string
age int
}
type admin struct{
user //嵌入user型別
level int
}
//使用user型別的值作為接收者實現Speaker介面
func (u user) speak(content string){
fmt.Println(u.name,":",content)
}
//使用admin型別的值作為接收者實現Speaker介面
func (a admin) speak(content string){
fmt.Println(a.name,"-",a.level,":",content)
}
func main(){
//初始化一個admin型別的物件
ad := admin{
user:user{
name:"zhongzhong",
age:25,
},
level:1,
}
//使用內部型別呼叫
ad.user.speak("你好啊")
//直接使用外部型別呼叫
ad.speak("你好")
fmt.Println("mian函式執行完成")
}
//zhongzhong : 你好啊
//zhongzhong - 1 : 你好
//mian函式執行完成
複製程式碼
從上面的輸出結果可以看出,如果外部型別和內部型別實現了同樣的介面,那麼使用外部型別呼叫介面的方法的時候,就是呼叫外部型別實現的方法而不再是內部型別的方法。也就是說,外部型別的方法會覆蓋內部型別的方法。這和java中的重寫類似。
來看一個複雜點的例子:
package main
import (
"fmt"
)
type Speaker interface{
speak(content string)
}
type user struct{
name string
age int
}
type speakerA struct{
propA int
}
type admin struct{
user //嵌入user型別
speakerA //嵌入speakerA型別
level int
}
//使用user型別的值作為接收者實現Speaker介面
func (u user) speak(content string){
fmt.Println(u.name,":",content)
}
//使用speakerA型別的值作為接收者實現Speaker介面
func (s speakerA) speak(content string){
fmt.Println(s.propA,":",content)
}
func main(){
//初始化一個admin型別的物件
ad := admin{
user:user{
name:"zhongzhong",
age:25,
},
speakerA:speakerA{
propA:100,
},
level:1,
}
//只能使用這種呼叫方式
ad.user.speak("你好啊")
//只能使用這種呼叫方式
ad.speakerA.speak("你好")
fmt.Println("mian函式執行完成")
}
//zhongzhong : 你好啊
//100 : 你好
//mian函式執行完成
複製程式碼
上面的程式碼,admin嵌入了user,speakerA兩種型別,而且這兩種型別都實現了Speaker介面。造成在使用外部型別物件呼叫的時候,go語言不知道如何處理。所以在這裡需要明確的使用內部型別物件來呼叫對應的方法。