【Go Trick】2.接口实现确认
接口概述
Go语言中的接口定义了一组方法的集合,接口本身不能实例化,需要具体的类型实现。
一个类型可以实现多个接口,如果该类型的包含了一个接口的所有同名方法,它就会自动实现这个接口。(接口即合约)
首先,接口只能声明方法,不能提供方法的具体实现。一个具体的类型实现了接口的全部方法,它就可以被视作实现了这个接口,可以将地址赋值给该接口类型的变量,类似于C++的基类指针,这是Go实现多态的关键。
如上,可以将Student
取地址,赋值给person
变量,通过person.getName()
即可调用Student的getName()
方法。
如果此时将Student
的getName()
方法注释掉,IDE就会高亮显示错误,编译也会有响应报错
接口实现检查
由于在Go语言中接口是一种合约,并不会显式地进行检查,如Java中的implements
关键字显式指定某个类实现某个接口,Go只会在结构体赋值给接口变量时才会进行判断。那么,如果代码中没有进行实际的多态操作,该怎么确保某个结构体实现特定的接口呢?在实际开发过程中,代码很庞杂,接口也可能有多个方法,难道只能一个个去比对方法名吗?
一个误区是,以为在结构体中包含匿名的接口类型成员变量就能显式指定接口的实现,如下
其实并非如此,这只是Go语言匿名嵌入的特性,代表Student
结构体有一个匿名的Person
成员,跟接口实现没有半毛钱关系。
正确的思路是,在定义完结构体之后,直接进行一次没有实际意义的强制类型转换不就好了?答案是这样
下面来解释一下这段代码,这就是Go编程常用到的接口检查器语法。var
代表进行一次全局变量的定义,_ Person
意思是一个匿名的Person
变量,等号右边则是对nil
空值进行强制类型转换,变成指针*Student
。这个语句能够编译成功的条件就是Person
类型的变量能接受*Student
类型的赋值,即Student
实现了Person
接口,而因为是定义了匿名变量,因此也不会对代码逻辑产生影响。
Go为了体现”接口即合约“的思想,让接口的实现变成隐式的,然而人们最终还是为了做显式确认,创造出了接口检查器语法,这是好是坏呢,Go语言的设计者乐见这一点吗?