匿名组合
确切地说,Go语言也提供了继承,但是采用了组合的文法,所以我们将其称为匿名组合:
type Base struct {
Name string
}
func (base *Base) Foo() { ... }
func (base *Base) Bar() { ... }
type Foo struct {
Base
...
}
func (foo *Foo) Bar() {
foo.Base.Bar()
...
}
以上代码定义了一个 Base 类(实现了 Foo() 和 Bar() 两个成员方法) ,然后定义了一个Foo 类,该类从 Base 类“继承”并改写了 Bar() 方法(该方法实现时先调用了基类的 Bar()方法) 。
在“派生类” Foo 没有改写“基类” Base 的成员方法时,相应的方法就被“继承” ,例如在上面的例子中,调用 foo.Foo() 和调用 foo.Base.Foo() 效果一致。
与其他语言不同,Go语言很清晰地告诉你类的内存布局是怎样的。此外,在Go语言中你还
可以随心所欲地修改内存布局,如:
type Foo struct {
... // 其他成员
Base
}
这段代码从语义上来说,和上面给的例子并无不同,但内存布局发生了改变。 “基类” Base
的数据放在了“派生类” Foo 的最后。另外,在Go语言中,你还可以以指针方式从一个类型“派生” :
type Foo struct {
*Base
...
}
这段Go代码仍然有“派生”的效果,只是 Foo 创建实例的时候,需要外部提供一个 Base 类实例的指针。