接口
- 接口用于定义对象的行为,接口只指定对象应该做什么,实现这种行为由对象来决定。
- 接口只是把所有具有共性的方法定义在一起,任何类型实现了接口中所有的方法,就是实现了这个接口。
- 接口存在的意义就是用来定义规范,用来做功能的拓展,好处是可以实现多态
- 在Go中只要接口中的方法和结构体中的一样,就会认为这么结构体实现了这个接口的方法
- 接口是引用类型,传值的时候是以引用方式(地址)传送进去的
接口定义及调用:
定义格式:
tepe 接口名 interface{方法名(参数) 返回值
}
调用格式1:
对象名.方法名
调用格式2:这种方式必须实现接口中声明的所有方法
通过接口变量调用
在代码中是体现不出来如何实现接口的,因为结构体和接口看似是没有任何关联的,其实Go中只要接口中的方法和结构体中的一样,就会认为这么结构体实现了这个接口的方法
type Student struct{}type Teacher struct{}type TestInterface interface {//age int // 接口中不能有变量//Welcome()Hello()
}type TestInterface2 interface {Hello2()
}// 一个结构体可以实现多个接口
func (student *Student) Hello() {fmt.Println("Student实现了接口的Hello方法")
}func (student *Student) Hello2() {fmt.Println("Student实现了接口的Hello2方法")
}func (teacher *Teacher) Hello() {fmt.Println("Teacher实现了接口的Hello方法")
}func main() {// 对象名.方法名var stu Studentstu.Hello()var tea Teachertea.Hello()// 通过接口变量调用,如果接口中有两个方法,但是只实现了一个,就会报错,必须全部实现var testInterface TestInterfacetestInterface = &stutestInterface.Hello()testInterface = &teatestInterface.Hello()
}
输出:
Student实现了接口的Hello方法
Teacher实现了接口的Hello方法
Student实现了接口的Hello方法
Teacher实现了接口的Hello方法
多态:
- 多态是同一个接口,使用不同的实例执行不同的操作
- 多态是除封装、继承之后面向对象的第三大特征。
- 多态是出现在接口关系中的(只能是接口)
- 举例:win电脑和Mac都是电脑(接口),但是mac只能办公用,win可以办公可以玩游戏,不同类型的电脑具有不同的特征,就是多态
多态的实现:
func 函数名 (参数 接口类型){}
演示:
func main() {var stu Studentvar tea Teacher// 多态,要加取地址符,因为方法是指针类型Polymorphic(&stu) //Student类实现了接口的Hello方法Polymorphic(&tea) // Teacher类实现了接口的Hello方法
}type Student struct{}type Teacher struct{}type TestInterface interface {Hello()
}func (student *Student) Hello() {fmt.Println("Student类实现了接口的Hello方法")
}func (teacher *Teacher) Hello() {fmt.Println("Teacher类实现了接口的Hello方法")
}func Polymorphic(polymorphic TestInterface) {polymorphic.Hello()
}
接口的继承与转换:
接口的继承和普通继承是一样的,直接写接口名就可以了,但是要实现继承接口的所有方法
func main() {var stu Studentvar testInterface02 TestInterface02// 接口中的方法数据类型是指针类型就要使用取地址符,如果方法的类型不是指针就不用加testInterface02 = &stutestInterface02.Hello() // 可以调用所继承接口中的方法testInterface02.HelloHello()var test TestInterfacetest = testInterface02test.Hello()
}type Student struct{}type TestInterface interface {Hello()
}type TestInterface02 interface {TestInterface // 继承接口HelloHello()
}func (student *Student) Hello() {fmt.Println("Hello")
}func (student *Student) HelloHello() {fmt.Println("HelloHello")
}
空接口定义及使用:
空接口(interface {})不包含任何的方法,正因为如此,所有的类型都实现了空接口,因此空接口可以存储任意类型的数值
func main() {// 定义空接口的切片,由于是空接口所以可以存储任意类型的数据var s []interface{}s = append(s, 1, 2, 3, "字符串", 1.1, true)fmt.Println(s)
}
map和切片也可以使用空接口
func main() {m := make(map[string]interface{})m["打野"] = "韩信"fmt.Println(m)i := []interface{}{1, 2, 3, 4.5, "哈哈", true}fmt.Println(i)
}
类型断言:
通过类型断言,可以判断空接口中存储的数据类型
定义格式:
value,ok:=m.(T)
- value:表示变量m的值
- ok:表示布尔类型变量,如果断言成功为true,否则为false
- m:表示空接口类型的变量,如果推断成功就把数据赋值给value
- T:表示断言的类型
演示:
func main() {var i interface{}i = 123// 如果i是int类型就会把结果赋值给ok,把数据(123)赋值给valuevalue, ok := i.(int)// 如果是123就会打印断言成功,不是123就会打印断言失败if ok {fmt.Println("断言成功:", value)} else {fmt.Println("断言失败")}
}
计算器案例:
func main() {var c ObjectInitializationresult := c.Create("+", 1, 2)fmt.Println(result)
}// 接口
type Calculate interface {GetResult() int
}// 公共参数类
type Num struct {num1, num2 int
}// 加法类
type Add struct {Num
}func (add *Add) GetResult() int {return add.num1 + add.num2
}// 减法类
type Sub struct {Num
}func (sub *Sub) GetResult() int {return sub.num1 - sub.num2
}// 乘法类
type Multiplication struct {Num
}func (multiplication *Multiplication) GetResult() int {return multiplication.num1 * multiplication.num2
}// 除法类
type DivisionMethod struct {Num
}func (divisionMethod *DivisionMethod) GetResult() int {return divisionMethod.num1 / divisionMethod.num2
}// 用于完成选择哪个方法的调用
type ObjectInitialization struct{}func InvokingFunction(c Calculate) int {return c.GetResult()
}
func (o *ObjectInitialization) Create(oi string, num1, num2 int) int {switch oi {case "+":add := Add{Num{num1, num2}}return InvokingFunction(&add)case "-":sub := Sub{Num{num1, num2}}return InvokingFunction(&sub)default:return 0}
}