如:
package main
import "fmt"
// X
type X struct {
a int
}
func (x X) Print() {
fmt.Printf("In X, a = %d\n", x.a)
}
func (x X) XPrint() {
fmt.Printf("call XPrint(). In X, a = %d\n", x.a)
}
// Y
type Y struct {
X
b int
}
func (y Y) Print() {
fmt.Printf("In Y, b = %d\n", y.b)
}
// Z
type Z struct {
Y
c int
}
func (z Z) Print() {
fmt.Printf("In Z, c = %d\n", z.c)
//显式的完全路径调用内嵌字段的方法
z.Y.Print()
z.Y.X.Print()
}
func main() {
x := X{a: 1}
y := Y{
X: x,
b: 2,
}
z := Z{
Y: y,
c: 3,
}
//从外向内查找,首先找到的是 Z 的 Print() 方法
z.Print()
//从外向内查找,最后找到的是 x 的 XPrint()方法
z.XPrint() // ->外层结构体自动获得了内部成员的方法
z.Y.XPrint()
}
>>>
In Z, c = 3
In Y, b = 2
In X, a = 1
call XPrint(). In X, a = 1
call XPrint(). In X, a = 1
go没有继承只有组合,组合实现了继承的效果
package main
import (
"fmt"
)
type Base struct {
// nothing
}
func (b *Base) F1() {
fmt.Println("Base.F1")
b.F2()
}
func (b *Base) F2() {
fmt.Println("Base.F2")
}
type Derived struct {
Base
}
func (d *Derived) F2() {
fmt.Println("Derived.F2")
}
func main() {
d := &Derived{}
d.F1()
}
>>>
Base.F1
Base.F2
// 不会打印"Derived.F2"
// Derived结构体自动含有了Base的方法,虽然重写了F2()方法,
// 但因为go没有继承只有组合,不会根据对象的不同来执行不同的F2(),调用的b.F2()仍然是*Base的F2()方法
golang如何实现多态的效果?--使用interface
package main
import (
"fmt"
)
// 首先需要一个接口,起到类似基类的作用
type B interface{
F1()
F2()
}
// 表示Base结构体含有一个实现了F1()和F2()的成员
type Base struct {
B
}
// Base重写了F1,没有重写F2()
// 根据结构体的组合关系,b.F2()到底调用哪个F2,需要从Base结构体出发,从外到内从上到下寻找最近的F2
// 因为Base没有重写F2(), 所以最近的F2就是Base.B.F2()
func (b *Base) F1() {
fmt.Println("Base.F1")
b.F2() // will call Base.B.F2()
}
type BaseBase struct {
Base
}
func (b *BaseBase) F2() {
fmt.Println("BaseBase.F2")
}
type Derived struct {
BaseBase
}
func (d *Derived) F2() {
fmt.Println("Derived.F2")
}
func main() {
ori_impl_1 := &BaseBase{}
// 重要!!!
// ###将ori_impl_1作为最底层的B接口实现,就可以调用ori_impl_1的F2###
var b B = &BaseBase{Base{B:ori_impl_1}}
b.F1()
ori_impl_2 := &Derived{}
// 将ori_impl_2作为最底层的B接口实现
var d B = &Derived{BaseBase{Base{B:ori_impl_2}}}
d.F1()
}
>>>
Base.F1
BaseBase.F2
Base.F1
Derived.F2
核心思想就是,外层实现接口,通过递归嵌套将被实现的接口实例置于内层,从而达到外层定义,内层使用的效果:
BaseBase和Derived都是外层结构体,在它们这一层实现了F2()。ori_impl_1以及ori_impl_2都是外层结构体实现的B接口实例,置于内层完成调用
匿名结构体
struct中的字段可以不用给名称,这时称为匿名字段。匿名字段的名称强制和类型相同。例如:
type animal struct {
name string
age int
}
type Horse struct{
int
animal
sound string
}
// Horse等价于
type Horse struct{
int int
animal animal
sound string
}
struct递归嵌套
如果struct中嵌套的struct类型是自己的指针类型,可以用来生成链表或二叉树等数据结构
例如,定义一个单链表数据结构
type Node struct {
Data string
Next *Node
}