10.1 接口
接口用于实现面向对象中的多态。
接口也是可以嵌套的。
一个接口是很多个方法的集合,但是这些方法不用实现,由实现这个接口的类型去实现。
也就是说,实现了接口里的全部方法,也就实现了这个接口。
下面声明了一个Man接口,man结构体类型实现了Man的全部方法,也就是man实现了接口Man。
package mainimport "fmt"//定义一个Man接口,有两个方法,run和singtype Man interface {run()sing()}//man结构体type man struct {}//实现run方法func (m *man) run() {fmt.Println("我是双脚走的")}//实现sing方法func (m *man) sing() {fmt.Println("我用嘴唱歌")}func main() {var me Man //声明接口var m1 man //声明结构体me = &m1 //结构体变量赋值给接口me.run()me.sing()}
有什么用呢?这里完全可以不用接口啊,直接用结构体调用方法就可以。
var m1 manm1.run()m1.sing()
但是,如果还有其他类型,其他结构体也实现了这个接口,但是不一样的实现。此时,如果调用方法,就是有多少个结构体,就要调用多少次run方法。
var m1 manm1.run()m1.sing()var m2 womanm2.run()m2.sing()......
接口的作用就体现出来了,比如上述的例子,还有一个woman结构体也实现了接口,那么,想要它们调用同一个函数时,有不一样的输出,就是接口的作用,多态。
package mainimport "fmt"//定义一个Man接口,有两个方法,run和singtype Man interface {run()sing()}//man结构体type man struct {}//实现run方法func (m *man) run() {fmt.Println("我是双脚走的")}//实现sing方法func (m *man) sing() {fmt.Println("我用嘴唱歌")}type woman struct {}//实现run方法func (m *woman) run() {fmt.Println("我是单脚走的")}//实现sing方法func (m *woman) sing() {fmt.Println("我不用嘴唱歌")}func Run(p Man) {p.run()p.sing()}func main() {Run(&man{}) //同时调用Run方法Run(&woman{}) //各自输出}
再来一个直观点的例子:
一个Dog接口,两个结构体jinmao和chaiquan,都实现了接口Dog,在add函数种,接收参数类型是接口,然后不同的接口变量调用同一个getage()函数,得到不一样的age,而不用写两遍。这里如果是成千上万个用户,那么效果更加明显,如果没有接口,那么就需要调用成千上万次getage()。
package mainimport "fmt"type Dog interface {getage() int}type jinmao struct{ age int }type chaiquan struct{ age int }func (j jinmao) getage() int {return j.age}func (c chaiquan) getage() int {return c.age}func add(s []Dog) {var sum intfor _, i := range s {sum += i.getage() //接口的真正意义}fmt.Println(sum)}func main() {jj := jinmao{1}cc := chaiquan{2}sdog := []Dog{jj, cc}add(sdog)}
10.2 类型断言
如何检测和转换接口变量的类型?一个接口类型的变量可以包含任意类型的值,必须有一种方式来检测它的到动态类型,即运行时在变量中存储的值的实际类型。利用类型断言来测试某个时刻接口变量是否包含某个类型的值:
if v, ok := vari.(*T); ok {fmt.Printf("变量var1的类型为: %T", v)} else {fmt.Println("变量var1不包含类型: ", v)}
例子:
package mainimport "fmt"//定义一个Man接口type Man interface {run()}//man结构体type man struct {name stringage int}//实现run方法func (m *man) run() {fmt.Println("我是双脚走的")}type woman struct {}//实现run方法func (m *woman) run() {fmt.Println("我是单脚走的")}func main() {var vari Manman1 := man{}vari = &man1if v, ok := vari.(*man); ok {fmt.Printf("变量var1的类型为: %T", v) //*main.man} else {fmt.Println("变量var1不包含类型: ", v)}if u, ok := vari.(*woman); ok {fmt.Printf("变量var1的类型为: %T", u)} else {fmt.Printf("变量var1不包含类型: %T", u) //*main.woman}}
10.3 类型判断:type-swith
接口变量的类型也可以使用一种特殊形式的switch来检测,不用if来判断:
package mainimport ("fmt")//定义一个Man接口type Man interface {run()}//man结构体type man struct {name stringage int}//实现run方法func (m *man) run() {fmt.Println("我是双脚走的")}type woman struct {}//实现run方法func (m *woman) run() {fmt.Println("我是单脚走的")}func main() {var vari Manman1 := man{}vari = &man1switch t := vari.(type) {case *man:fmt.Printf("类型%T,值为%v", t, t) //类型*main.man,值为&{ 0}case *woman:fmt.Printf("类型%T,值为%v", t, t)case nil:fmt.Printf("nil 值")default:fmt.Println("未知类型")}}
接口的不写了,没搞懂………
