041-struct 结构体(三)

Golang 的 struct 结构体注定是不平凡的。

今天要讨论的话题是结构体嵌套。这很平凡,无论是 C/C++,结构体里套结构体不是一件很寻常的事吗?为什么 Go 里又说不平凡呢?

1. 结构体嵌套

先来看两个结构体的定义:

type Point struct {
    X, Y int // 这个语法是你一次见到,如果相邻连续的字段类型一样,可以连写成一行
}

type Circle struct { // 这是一个圆的定义
    p Point // 圆心坐标
    r float64 // 半径
}

看到上面的 Circle 定义你一定不觉得奇怪。来看看如何定义一个 Circle.

c := Circle{Point{10, 10}, 6.4}
fmt.Println(c)              // {{10 10} 6.4}
fmt.Println(c.p)            // {10 10}
fmt.Println(c.r)            // 6.4
fmt.Println(c.p.X)          // 10
fmt.Println(c.p.Y)          // 10

除了使用上面的定义方式,你还可以:

a := Circle{} // 定义一个 0 值初始化的对象
b := Circle{p: Point{Y: 4}} // 指定字段名称赋值

这看起来似乎没有什么神奇的。不过,好戏在后头。

2. 匿名结构体成员

还是上面的 Point 和 Circle 定义

type Point struct {
    X, Y int
}

type Circle struct {
    Point // 没有名字的圆心
    r float64
}

没错,Go 允许这样做。这样有什么好处呢?不妨再看下面使用 Circle 声明对象的方法:

c := Circle{Point{10, 10}, 6.4} // 定义方法和前面如出一辙
// c := Circle{11, 11, 6.4} // not ok
fmt.Println(c)
fmt.Println(c.r)
fmt.Println(c.Point.X) // 可以通过结构体名称使用其字段
fmt.Println(c.Y) // 甚至可以这样直接使用 Point 的字段
  • 注意:因为匿名成员没有名字,这意味着你无法同时定义两个类型一样的匿名成员,比如下面这样是不行的:
// 编译时会报:duplicate field Point
type Circle struct {
    Point
    Point
    r float64
}

3. 总结

到这里有同学要问了,这样有啥好处?

学过面向对象语言的同学一定听说过 inherit (继承)的概念。没错,Golang 就是通过嵌套匿名成员就可以达到继承的效果,是不是很有意思?

不过在 Go 里,这种做法不称为继承,而是 composition (组合)这,这是 Go 语言 oop 编程思想的核心。

最后,关于结构体我们暂且先介绍到这里。

结构体的知识当然远远不止这些,但是目前为止我们还不能快马加鞭一次性全说完,因为你还需要一些额外的基础做铺垫,所以继续前进吧!

  • 掌握匿名成员
  • 掌握访问匿名成员字段的方法

猜你喜欢

转载自blog.csdn.net/q1007729991/article/details/80358148
今日推荐