Go 语言虽然抛弃了继承,但是却提供了一个更加方便的组合特性。相对于继承的编译期确定实现,组合的运行态指定实现,更加灵活。下面通过一段代码来了解组合的基本属性以及它与继承的不同之处。

先定义一个结构体 Base, 并为它添加两个方法 Foo()Bar()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
type Base struct{
Name string
}

func (b *Base) Foo() {...}
func (b *Base) Bar() {...}

type Seed struct {
Base
...
}

func (s *Seed) Foo() {
s.Base.Foo()
s.Bar()
...
}

上面代码先定义了一个 Base 类,然后定义了一个 Seed 类。Seed 类“继承”了 Base 类的所有成员属性和方法并重写了 Foo() 方法。同时在重写 Foo() 方法时调用了 Base 类的 Foo() 方法和 Bar() 方法。需要注意的是,若此时 Seed 的对象通过 s.Foo() 调用 Foo() 方法时,实际调用的是 Seed 重写过后的 Foo() 方法,而不是基类 Base 的 Foo() 方法,若想调用 Base 类的 Foo() 方法则要使用 s.Base.Foo,而调用没有重写的 Bar() 方法时,使用 s.Bar()s.Base.Bar() 效果是一样的。