1、接口的引入
以日常生活中打招呼为例,定义接口规范,各国人为打招呼为具体的实现
package main
import "fmt"
//接口的定义:定义规则、定义规范,定义某种能力:
type SayHello interface{
//声明没有实现的方法:
sayHello()
}
=========================================分割线
//接口的实现:定义一个结构体:
//中国人:
type Chinese struct{
}
//实现接口的方法---》具体的实现:
func (person Chinese) sayHello(){
fmt.Println("你好")
}
=========================================分割线
//接口的实现:定义一个结构体:
//美国人:
type American struct{
}
//实现接口的方法---》具体的实现:
func (person American) sayHello(){
fmt.Println("hi")
}
=========================================分割线
//定义一个函数:专门用来各国人打招呼的函数,接收具备SayHello接口的能力的变量:
func greet(s SayHello){
s.sayHello()
}
=========================================分割线
//测试
func main(){
//创建一个中国人:
c := Chinese{}
//创建一个美国人:
a := American{}
//美国人打招呼:
greet(a)
//中国人打招呼:
greet(c)
}
2、接口
- 接口中不能包含任何变量
- 接口中定义一组方法,但不需要实现
- Go中没有implements关键字,实现接口要实现所有的方法才是实现,即Go的实现是基于方法的
3、接口的注意点
1)接口本身不能创建实例,但是可以指向一个实现了该接口的自定义类型的变量
//直接用接口创建实例并调用方法,编译报错
//var s SayHello
//s.sayHello()
c := Chinese{}
var s SayHello = c
s.sayHello()
2)只要是自定义数据类型,就可以实现接口,不仅仅是结构体类型
3)一个自定义类型可以实现多个接口
package main
import "fmt"
type AInterface interface{
a()
}
type BInterface interface{
b()
}
type Stu struct{
}
//实现接口A(的方法)
func (s Stu) a(){
fmt.Println("aaaa")
}
//实现接口B(的方法)
func (s Stu) b(){
fmt.Println("bbbb")
}
func main(){
var s Stu
var a AInterface = s //注意这里的赋值
var b BInterface = s //注意这里的赋值
a.a()
b.b()
}
4)一个接口(比如A接口)可以继承多个别的接口(比如B,C接口),这时如果要实现A接口,也必须将B,C接口的方法也全部实现
package main
import "fmt"
//C接口
type CInterface interface{
c()
}
//B接口
type BInterface interface{
b()
}
//A接口继承了B、C接口,且有自己的方法a()
type AInterface interface{
BInterface
CInterface
a()
}
//Stu结构体实现A接口,也要去实现B、C接口的方法
type Stu struct{
}
func (s Stu) a(){
fmt.Println("a")
}
func (s Stu) b(){
fmt.Println("b")
}
func (s Stu) c(){
fmt.Println("c")
}
func main(){
var s Stu
var a AInterface = s
a.a()
a.b()
a.c()
}
5)interface类型默认是一个指针(引用类型),如果没有对interface初始化就使用,那么会输出nil
6)空接口没有任何方法,所以可以理解为所有类型都实现了空接口,也可以理解为我们可以把任何一个变量赋给空接口
注意上面两种空接口类型的写法,一种是自己定义一个:
type E interface{
}
Var e E = s
也可:
var e interface{} = s
4、多态
面向对象的最后一个特征:多态,即多种形态,编译时、运行时两种状态。Go中的多态特征是通过接口实现的,可以按照统一的接口来调用不同的实现。如上面Part1中的SayHello,形参就是一个父类接口:
再比如定义SayHello数组,存放中国人结构体、美国人结构体
5、断言
直接判断是否是该类型的变量,Java的instanceOf
value, ok := element.(T)
即,element是否为T类型,是转为T,值为value,且ok为true
package main
import "fmt"
//接口的定义:定义规则、定义规范,定义某种能力:
type SayHello interface{
//声明没有实现的方法:
sayHello()
}
//接口的实现:定义一个结构体:
//中国人:
type Chinese struct{
name string
}
//实现接口的方法---》具体的实现:
func (person Chinese) sayHello(){
fmt.Println("你好")
}
//中国人特有的方法
func (person Chinese) niuYangGe(){
fmt.Println("东北文化-扭秧歌")
}
//接口的实现:定义一个结构体:
//美国人:
type American struct{
name string
}
//实现接口的方法---》具体的实现:
func (person American) sayHello(){
fmt.Println("hi")
}
//定义一个函数:专门用来各国人打招呼的函数,接收具备SayHello接口的能力的变量:
func greet(s SayHello){
s.sayHello()
//断言:
ch,flag := s.(Chinese)//看s是否能转成Chinese类型并且赋给ch变量,flag是判断是否转成功
if flag == true{
ch.niuYangGe()
}else{
fmt.Println("美国人不会扭秧歌")
}
fmt.Println("打招呼。。。")
}
func main(){
//创建一个中国人:
//c := Chinese{}
//创建一个美国人:
a := American{}
//美国人打招呼:
greet(a)
//中国人打招呼:
//greet(c)
}
关键点:
6、Type Switch
一种特殊的switch语句,用type关键字。用法:
//定义一个函数:专门用来各国人打招呼的函数,接收具备SayHello接口的能力的变量:
func greet(s SayHello){
s.sayHello()
switch s.(type){//type属于go中的一个关键字,固定写法
case Chinese:
ch := s.(Chinese)
ch.niuYangGe()
case American:
am := s.(American)
am.disco()
}
fmt.Println("打招呼。。。")
}
完整示例:
package main
import "fmt"
//接口的定义:定义规则、定义规范,定义某种能力:
type SayHello interface{
//声明没有实现的方法:
sayHello()
}
//接口的实现:定义一个结构体:
//中国人:
type Chinese struct{
name string
}
//实现接口的方法---》具体的实现:
func (person Chinese) sayHello(){
fmt.Println("你好")
}
//中国人特有的方法
func (person Chinese) niuYangGe(){
fmt.Println("东北文化-扭秧歌")
}
//接口的实现:定义一个结构体:
//美国人:
type American struct{
name string
}
//实现接口的方法---》具体的实现:
func (person American) sayHello(){
fmt.Println("hi")
}
func (person American) disco(){
fmt.Println("野狼disco")
}
//定义一个函数:专门用来各国人打招呼的函数,接收具备SayHello接口的能力的变量:
func greet(s SayHello){
s.sayHello()
switch s.(type){//type属于go中的一个关键字,固定写法
case Chinese:
ch := s.(Chinese)
ch.niuYangGe()
case American:
am := s.(American)
am.disco()
}
fmt.Println("打招呼。。。")
}
func main(){
//创建一个中国人:
c := Chinese{}
//创建一个美国人:
//a := American{}
//美国人打招呼:
//greet(a)
//中国人打招呼:
greet(c)
}