规则说明
- 方法继承:当一个结构体类型嵌入另一个类型时,外部结构体将“继承”嵌入类型的方法集。这意味着外部结构体的实例可以直接调用嵌入类型的方法,就好像这些方法是外部结构体自己定义的一样。
- 方法覆盖:如果外部结构体定义了与嵌入类型同名的方法,那么外部结构体定义的方法将覆盖嵌入类型的方法。在这种情况下,外部结构体实例调用该方法时,将执行外部结构体定义的方法。
- 方法可见性:嵌入类型的方法遵循正常的Go语言可见性规则。如果嵌入类型的方法是导出的(首字母大写),那么外部结构体的实例可以在包外调用该方法;如果是未导出的(首字母小写),则只能在包内调用。
示例代码
package main
import "fmt"
// 基础结构体1
type Component1 struct {
Name string
}
func (c Component1) Method1() {
fmt.Printf("Component1's Method1: Name is %s\n", c.Name)
}
// 基础结构体2
type Component2 struct {
Value int
}
func (c Component2) Method2() {
fmt.Printf("Component2's Method2: Value is %d\n", c.Value)
}
// 中间结构体
type Intermediate struct {
Component1
Component2
}
func (i Intermediate) Method2() {
fmt.Printf("Intermediate's Method2 overrides Component2's Method2, Value is %d\n", i.Value)
}
// 复杂结构体
type Complex struct {
Intermediate
Extra string
}
func main() {
c := Complex{
Intermediate: Intermediate{
Component1: Component1{Name: "Embedded1"},
Component2: Component2{Value: 42},
},
Extra: "Some extra data",
}
c.Method1()
c.Method2()
}
方法调用过程分析
- 调用
c.Method1()
:
Complex
结构体嵌入了 Intermediate
结构体,而 Intermediate
又嵌入了 Component1
结构体。
- 当
c.Method1()
被调用时,Go语言会在 Complex
的方法集中查找 Method1
。由于 Complex
没有直接定义 Method1
,它会沿着嵌入链向上查找。
- 找到
Component1
中的 Method1
方法,然后执行该方法,打印出 Component1's Method1: Name is Embedded1
。
- 调用
c.Method2()
:
Complex
结构体嵌入了 Intermediate
结构体,Intermediate
嵌入了 Component2
结构体,且 Intermediate
和 Component2
都定义了 Method2
方法。
- 当
c.Method2()
被调用时,Go语言首先在 Complex
的方法集中查找 Method2
,未找到。
- 然后在嵌入的
Intermediate
结构体的方法集中查找,找到了 Intermediate
定义的 Method2
方法(此方法覆盖了 Component2
的 Method2
),执行该方法,打印出 Intermediate's Method2 overrides Component2's Method2, Value is 42
。