『就要學習 Go 語言』系列 -- 第 25 篇分享好文golang
Go 語言沒有對象的概念,可是 struct 類型有着和對象相似的特性。struct 類型能夠定義本身的屬性和方法。這篇文章咱們來總結下 Go 語言中關於 「繼承」 和多態的概念。函數
嵌入類型是指將已有的類型直接聲明在新的結構類型裏。不像 Java、C++ 等語言,Go 語言沒有繼承,可是能夠經過組合的方式實現代碼的複用。post
type User struct {
Name string
Email string
}
type Admin struct {
User
Level string
}
func (u *User) Speak() {
fmt.Println("I am user",u.Name)
}
複製代碼
上面的代碼定義了兩個結構體 User 和 Admin,Admin 有一個匿名成員 User,由於是匿名,因此類型即名稱。將 User 嵌入 Admin,Admin 是被嵌入的類型,也稱外部類型,User 是內部類型。Speak() 是 User 的方法。學習
經過嵌入,內部類型的屬性、方法,能夠爲外部類型全部,就好像是外部類型本身的同樣。此外,外部類型還能夠定義本身的屬性和方法,甚至能夠定義與內部相同的方法,這樣內部類型的方法就會被「屏蔽」。spa
admin := Admin{
User:User{
Name:"Jack",
Email:"Jack@gmail.com",
},
Level:"admin",
}
// 內部類型的方法也被提高到外部類型
admin.Speak() // 方式一
// 直接訪問內部類型的方法
admin.User.Speak() // 方式二
複製代碼
輸出:.net
I am user Jack
I am user Jack
複製代碼
給 Admin 定義本身的 Speak() 方法:指針
func (a *Admin) Speak() {
fmt.Println("I am admin",a.Name)
}
func main() {
admin := Admin{
User:User{
Name:"Jack",
Email:"Jack@gmail.com",
},
Level:"admin",
}
admin.Speak() // 方式一
admin.User.Speak() // 方式二
}
複製代碼
輸出:code
I am admin Jack
I am user Jack
複製代碼
能夠看到,Admin 定義了本身的 Speak() 方法時,會自動調用本身的方法,而屏蔽內部類型的方法。對於屬性也是同樣的狀況。
查看完整代碼cdn
另外,更重要的是,若是內部類型實現接口 A,也能夠認爲外部類型也實現了接口 A。對象
type Speaker interface {
Speak() // 方法
}
func gotoSpeak(s Speaker) {
s.Speak()
}
複製代碼
定義了 Speaker 接口,任意類型若是實現了接口中定義的所有方法,就認爲該類型實現了接口。例如,上面定義的 User 類型,就實現了接口 Speaker。gotoSpeak() 函數是接收 Speaker 接口類型的參數,任何實現了 Speaker 接口的類型均可以調用該函數。
admin := Admin{
User: User{
Name: "Jack",
Email: "Jack@gmail.com",
},
Level: "admin",
}
gotoSpeak(&admin)
複製代碼
輸出:
I am user Jack
複製代碼
注意,關鍵點來了,調用 gotoSpeak() 時傳的參數是 admin 的地址,類型是 *Admin,不能傳 Admin 類型的值。從上篇文章咱們知道,Admin 類型的方法集中不包括 Speak() 方法,也就是說 Admin 類型沒有實現 Speaker 接口。
結合上篇關於類型方法集,對於嵌入類型的內部類型方法的提高能夠總結下。假設外部結構體類型是 S,內部類型是 T,則關於內部類型的方法提高以下規則:
上面的三條規則能夠總結成一句話:無論是 T 嵌入 S,仍是 *T 嵌入 S,外部類型 S 惟獨經過值類型不能調用內部類型 T 的指針方法外,其餘狀況下內部類型 T 的方法均可以得到提高,便可被外部類型 S 訪問 。
前兩點其實很好理解,第三點是經過指針方式組合,其實就是在外部類型初始化的時候,取得內部類型的指針。其餘規則與非指針方式組合一致。
type Admin struct {
*User // 經過指針方式組合
Level string
}
func main() {
admin := Admin{
User: &User{
Name: "Jack",
Email: "Jack@gmail.com",
},
Level: "admin",
}
gotoSpeak(&admin)
gotoSpeak(admin)
}
複製代碼
輸出:
I am user Jack
I am user Jack
複製代碼
其實上面的例子已經給出多態的例子了,這個給你們提一下。在 Go 語言中,每種類型都是不一樣的,但不一樣的類型能夠實現同一接口,將它們綁定在同一接口上,用做函數或者放的輸入(輸出)參數。例如上面的 User 類型和 Admin 類型就是經過 Speaker 接口創建了關係。
深刻閱讀:
1.教女友寫方法(續)
2.Polymorphism - OOP in Go
3.Is Go An Object Oriented Language?
4.《Go 語言實戰》5.4 5.5 節
原創文章,若需轉載請註明出處!
歡迎掃碼關注公衆號「Golang來啦」或者移步 seekload.net ,查看更多精彩文章。
給你準備了學習 Go 語言相關書籍,公號後臺回覆【電子書】領取!