结构体中嵌入结构体后的方法集合

结构体中嵌入结构体后的方法集合

结构体中嵌入结构体后的方法集合 #

在结构体类型中嵌入结构体类型,为 Gopher 们提供了一种“实现继承”的手段,外部的结构体类型 T 可以“继承”嵌入的结构体类型的所有方法的实现。并且,无论是 T 类型的变量实例还是 *T 类型变量实例,都可以调用所有“继承”的方法。但这种情况下,带有嵌入类型的新类型究竟“继承”了哪些方法,我们还要通过下面这个具体的示例来看一下。

type T1 struct{}
func (T1) T1M1()   { println("T1's M1") }
func (*T1) PT1M2() { println("PT1's M2") }
type T2 struct{}
func (T2) T2M1()   { println("T2's M1") }
func (*T2) PT2M2() { println("PT2's M2") }
type T struct {
    T1
    *T2
}
func main() {
    t := T{
        T1: T1{},
        T2: &T2{},
    }
    dumpMethodSet(t)
    dumpMethodSet(&t)
}

结构体类型 T 有两个嵌入字段,分别是 T1 和 *T2,我们知道 T1 与 *T1、T2 与 *T2 的方法集合是不同的:

  1. T1 的方法集合包含:T1M1;
  2. *T1 的方法集合包含:T1M1、PT1M2;
  3. T2 的方法集合包含:T2M1;
  4. *T2 的方法集合包含:T2M1、PT2M2。

它们作为嵌入字段嵌入到 T 中后,对 T 和 *T 的方法集合的影响也是不同的。我们运行一下这个示例,看一下输出结果:

main.T's method set:
- PT2M2
- T1M1
- T2M1
*main.T's method set:
- PT1M2
- PT2M2
- T1M1
- T2M1

通过输出结果,我们看到了 T 和 *T 类型的方法集合果然有差别的:

  1. 类型 T 的方法集合 = T1 的方法集合 + *T2 的方法集合
  2. 类型 *T 的方法集合 = *T1 的方法集合 + *T2 的方法集合

我们尤其要注意 *T 类型的方法集合,它包含的可不是 T1 类型的方法集合,而是 *T1 类型的方法集合。这和结构体指针类型的方法集合包含结构体类型方法集合,是一个道理。

Viewpoint #

From #

26|方法:如何用类型嵌入模拟实现“继承”?