思想:
duck typing - 鸭子类型:
当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。
意思就是说:
研究一个东西究竟是不是鸭子,取决于它能不能满足鸭子的工作。
接口:
go通过接口实现了类型安全的鸭子类型,同时又避免了OOP编程中的继承,我们来学习下go的接口(interface)。
go的接口是一种抽象的可以自定义的类型
,没法直接实例化,它声明了一个或者多个方法的签名。如果一个 struct 实现了一个 接口定义的所有方法 ,我们就说这个 struct 实现了这个 接口
。
注意:
这里的“实现”是隐式的,你不用显示声明某个struct实现了哪个接口。
实例:
首先,我们通过 interface 声明一个接口:
// Sleeper 接口声明
type Sleeper interface {
Sleep() // 声明一个 Sleep() 方法
}
下面,我们定义两个类型:
//定义一个 Dog 的结构体,其中有 1 个 Name 属性。
type Dog struct {
Name string
}
//思路:
// 我们如果想实现上面的 Sleeper接口,那么只要实现其中的方法即可。
// 下面我们为 Dog 添加一个方法 Sleep() :
func (d Dog) Sleep() {
fmt.Printf("Dog %s is sleeping\n", d.Name)
}
//我买再定义一个 Cat 的结构体,其中有 1 个 Name 属性。
type Cat struct {
Name string
}
func (c Cat) Sleep() {
fmt.Printf("Cat %s is sleeping\n", c.Name)
}
测试:
//参数: 只要是 Sleeper类型,都可以传入。
// 即只要是实现了这个接口的,都可以当做参数传进来。
func AnimalSleep(s Sleeper) {
s.Sleep()
}
func main() {
var s Sleeper
dog := Dog{Name: "xiaobai"}
cat := Cat{Name: "hellokitty"}
//思路:只要 dog 这个实例的类型实现了 Sleeper接口中的方法,就认为dog实现了Sleeper这个接口。
s = dog
AnimalSleep(s) // 使用 dog 的 Sleep()
s = cat
AnimalSleep(s) // 使用 cat 的 Sleep()
//创建一个 Sleeper 切片
sleepList := []Sleeper{Dog{Name: "xiaobai"}, Cat{Name: "kitty"}}
for _, s := range sleepList {
s.Sleep()
}
}
到这里我们就用 go 的接口实现了多态,我们先声明了一个接口类型的值,只要实现了这个接口的 struct 变量(dog cat),都可以赋值给它(Sleeper接口变量 s), 而调用方法的时候,go 会根据实际类型选择使用哪个 struct 的方法。
来源: