接口
- 接口是把所有具有共性的方法定义在一起,是方法集,任何类型实现了接口中所有的方法,就是实现了这个接口。
- 接口可以实现多态
- 接口传递的是地址值
接口定义及调用:
定义格式:
tepe 接口名 interface{
方法名(参数) 返回值
}
调用格式1:
对象名.方法名
调用格式2:通过接口变量调用必须实现接口所有方法
var 变量名 接口名
结构体和结构体指针实现接口
type TestInterface interface {
Hello()
}
func (s Student) Hello() {} // 使用结构体实现接口
func (s *Student) Hello() {} // 使用结构体指针实现接口
只要结构体和接口中的方法名一样,就会认为这么结构体实现了这个接口的方法
type Student struct{}
type Teacher struct{}
type TestInterface interface {
//age int // 接口中不能有变量
//Welcome()
Hello()
}
type TestInterface2 interface {
Hello2()
}
// 一个结构体可以实现多个接口
func (s *Student) Hello() {
fmt.Println("Student实现了Hello方法")
}
func (s *Student) Hello2() {
fmt.Println("Student实现了Hello2方法")
}
// 一个接口可以被多个结构体实现
func (t *Teacher) Hello() {
fmt.Println("Teacher实现了Hello方法")
}
func main() {
// 对象名.方法名
var stu Student
stu.Hello()
var tea Teacher
tea.Hello()
// 通过接口变量调用,如果接口中有两个方法,但是只实现了一个,就会报错,必须全部实现
var t TestInterface
t = &stu
t.Hello()
}
接口继承:
接口的继承和普通继承是一样的,直接写接口名就可以了,但是要实现继承接口的所有方法
func main() {
var stu Student
var t TestInterface02
// 接口中的方法数据类型是指针类型就要使用取地址符,如果方法的类型不是指针就不用加
t = &stu
t.Hello() // 可以调用所继承接口中的方法
t.HelloHello()
var test TestInterface
test = t
test.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")
}
空接口:
空接口不包含任何的方法,所有的类型都实现了空接口,因此空接口可以存储任意类型的数值
func main() {
// 定义空接口的切片,由于是空接口所以可以存储任意类型的数据
var s []interface{}
s = append(s, 1, 2, 3, "字符串", 1.1, true)
fmt.Println(s)
// map也可以使用接口
m := make(map[string]interface{})
m["打野"] = "韩信"
m["金币"] = 50
fmt.Println(m)
}
多态:
- 多态是同一个接口,使用不同的实例执行不同的操作
- 多态是除封装、继承之后面向对象的第三大特征。
- 多态是出现在接口关系中的(只能是接口)
例:汽车和摩托车都属于车,但具有不同的功能
多态的实现:
func 函数名 (参数 接口类型){}
演示:
func main() {
var stu Student
var 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(p TestInterface) {
p.Hello()
}
类型断言:
通过类型断言,可以判断空接口中存储的数据类型
定义格式:
value,ok:=m.(T)
- value:表示变量m的值
- ok:表示布尔类型变量,如果断言成功为true,否则为false
- m:表示空接口类型的变量,如果推断成功就把数据赋值给value
- T:表示断言的类型
演示:
func main() {
var i interface{}
i = 123
// 如果i是int类型就会把结果赋值给ok,把数据(123)赋值给value
value, ok := i.(int)
if ok {
fmt.Println("断言成功:", value)
} else {
fmt.Println("断言失败")
}
}
接口作为函数参数,断言也可以结合分支语句、循环语句
func main() {
var i interface{}
i = false
Test(i)
}
func Test(i interface{}) {
switch i.(type) {
case int:
fmt.Println("是int类型")
case bool:
fmt.Println("是bool类型")
case string:
fmt.Println("是string类型")
default:
fmt.Println("啥也不是")
}
}
计算器案例:
func main() {
var c ObjectInitialization
result := 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
}
}