在golang中,结构体 内嵌 结构体、接口 内嵌 接口 经常见,但 结构体 内嵌 匿名接口 可能会见得比较少,有什么场景可以这种用法呢?
当我们需要重写一个 “实现了某个接口的结构体” 的部分方法,而其它方法保持不变 的时候,就需要用到这种用法。
下面我们以计算器为例子进行说明。
代码定义一个计算器接口,拥有 加法 和 乘法 两个方法,并定义一个结构体实现这个接口,代码如下:
package main
import "fmt"
type Icalculator interface {
sum(a, b int) int // 加法
multiply(a, b int) int // 乘法
}
// 定义 MyCalc 结构体,并实现 Icalculator 接口中的方法
type MyCalc struct{}
func (obj MyCalc) sum(a, b int) int {
return a + b
}
func (obj MyCalc) multiply(a, b int) int {
return a * b
}
func main() {
myCalc := MyCalc{}
a, b := 5, 3
fmt.Printf("sum: %d, multiply: %d\n", myCalc.sum(a, b), myCalc.multiply(a, b))
// 输出:sum: 8, multiply: 15
}
至此,我们已经拥有了一个计算器结构体,并可以正常使用。
MyCalcsum
sum
那么,这时候就需要用到 结构体 内嵌 匿名接口 的用法了,代码如下:
package main
import "fmt"
type Icalculator interface {
sum(a, b int) int // 加法
multiply(a, b int) int // 乘法
}
// 定义 MyCalc 结构体,并实现 Icalculator 接口中的方法
type MyCalc struct{}
func (obj MyCalc) sum(a, b int) int {
return a + b
}
func (obj MyCalc) multiply(a, b int) int {
return a * b
}
// 新增定义一个 CustomCalc 结构体,并匿名内嵌 Icalculator 接口
type CustomCalc struct {
Icalculator
}
// 改写sum方法
func (obj CustomCalc) sum(a, b int) int {
return a - b
}
func main() {
myCalc := MyCalc{}
// 将myCalc传入CustomCalc结构体
customCalc := CustomCalc{myCalc}
a, b := 5, 3
fmt.Printf("sum: %d, multiply: %d\n", customCalc.sum(a, b), customCalc.multiply(a, b))
// 输出:sum: 2, multiply: 15
}
CustomCalcmyCalcCustomCalcsumsummyCalcsum
总结
结构体内嵌接口的作用:
- 不依赖具体实现:即接口为A,结构体B1、B2实现了接口A,结构体C内嵌了A,那么C.A可以通过B1/B2实例化;
- 对接口类型进行重写:当C.A通过B1实例化后,C和B1的关系,可以转变为结构体C内嵌结构体B1,那么C可以直接使用B1中的所有方法,当然C也可以对B1中的方法进行重写,这里官方文档这样解释“Interface and we can override a specific method without having to define all the others.”