Java中有内部类和匿名类的说法,但是Go的嵌入类和JAVA完全两回事。在Go语言中,新类可以嵌入一个已有类型作为内部类型,从而它就作为内部类型的外部类型。
通过嵌入类型,与内部类型相关的标识会被提升到外部类型上,就像直接被声明到外部类型一样,作为外部类型的一部分,并且可以添加新方法和属性。外部类型也可以声明新的与内部类型同名的标识符来覆盖内部类型的属性和方法,也即扩展。
下面看看示例:
package main
import (
"fmt"
)
type user struct {
name string
email string
}
func (u *user) notify() {
fmt.Printf("Sending user email to %s<%s>\n",
u.name, u.email)
}
type admin struct {
user // 嵌入类型
level string
}
func main() {
ad := admin{
user:user{
name:"john smith",
email:"john@yahoo.com",
},
level:"super",
}
//可以直接访问内部类型的方法
ad.user.notify()
// 内部类型的方法也被提升到外部类型
ad.notify()
}
Sending user email to john smithjohn@yahoo.com Sending user email to john smithjohn@yahoo.com
可以看到,既能通过内部类型访问方法,也可以当做自己类型访问。
对上面的代码修改,加入一个接口:
package main
import (
"fmt"
)
type notifyer interface {
notify()
}
func sendNotification(n notifyer) {
n.notify()
}
type user struct {
name string
email string
}
func (u *user) notify() {
fmt.Printf("Sending user email to %s<%s>\n",
u.name, u.email)
}
type admin struct {
user // 嵌入类型
level string
}
func main() {
ad := admin{
user:user{
name:"john smith",
email:"john@yahoo.com",
},
level:"super",
}
sendNotification(&ad)
}
Sending user email to john smithjohn@yahoo.com
可以看到,因为内部类型的方法被提升到外部类型,admin也实现了notifyer。
再在上面代码中加入一个方法:
func (a *admin) notify() {
fmt.Printf("Sending admin email to %s<%s>\n",
a.name, a.email)
}
Sending admin email to john smithjohn@yahoo.com
从结果可以看到,admin覆盖了user的方法。
总之,外部类型可以把内部类型的属性和方法提升为自己的一部分,也可以覆盖,覆盖后还能访问内部类型的值。
[1]. 《go语言实战》