interface 是什么
在讲解 interface 是什么之前,先让我们了解这个名词: duck typing
,翻译成中文就是 鸭子类型。我们来看 wiki 是怎样说明的:
鸭子类型(英语: duck typing )在程序设计中是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由 “ 当前方法和属性的集合 “ 决定。
换句话说,我们可以这样理解,鸭子类型是一种动态类型的风格,在这种类型中,我们只关注它们的方法,而不关注它们实际的数据类型。只要它们的方法相同,那么就是鸭子类型。
wiki 是这样解释的:
在鸭子类型中,关注点在于对象的行为,能作什么;而不是关注对象所属的类型。
而这种特性也是 鸭子类型的名字来源
“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”
光是文字难以理解,我们来看代码:
package main
import "fmt"
type Animal interface {
speak()
}
type person struct {
}
func (p person) speak() {
fmt.Println("I'm a man")
}
type dog struct {
}
func (d dog) speak() {
fmt.Println("I'm a dog")
}
// 看这里,我们传入了一个接口变量
func Speak(animal Animal) {
animal.speak()
}
func main() {
// 实例一个Animal 接口
var animal Animal
// 这里和下面为什么能够直接赋值,等会再讲
animal = person{}
Speak(animal)
animal = dog{}
Speak(animal)
}
运行结果:
I'm a man
I'm a dog
我们重点看两处调用 Speak() 的地方,我们分别传入 person{} 和 dog{}, 它们的类型显然是不同的,但是它们都使用了 speak() 方法,如果我们把 person 的 speak 方法注释掉,显然 传入 person 时是无法使用 speak 方法的。这里就已经比较清楚的表明 interface 是 duck typing 了。什么,你还是无法理解?你看, person 和 dog 类型不同,但它们都能够使用 speak 方法,这就已经符合 duck typing 的定义了。当然,你还无法理解,为什么是 struct 实现方法,却表明 interface 的属性,也无法理解为何 dog 和 person 能够直接赋值给 animal, 请继续看。
这里拓展一下, duck typing 一般是动态语言中才会出现,如 python, 为什么 Golang 能够使用?请自行了解。
现在我们已经明白了 duck typing 这种类型了,显然 interface 就是 duck typing 了,那么我们可以知道, interface 是 Golang 中具有 duck typing 类型的一种数据类型。