接口interface类型可以定义一组方法,但是这些方法不需要实现。并且interface不能包含任何变量。
某个自定义类型(比如结构体)要使用的时候.在根据具体情况把这些方法写出来(实现)。
示例代码:
下面声明了一个run接口,里面声明start和end方法。
然后rabbit和turtle结构体都定义了start和end方法。
competition结构体定了running方法,传的形参是run接口,方法里面直接调用了start和end。
package main
import "fmt"
type Run interface {
Start()
End()
}
type Rabbit struct {
}
func (r Rabbit) Start() {
fmt.Println("兔子跑步开始")
}
func (r Rabbit) End() {
fmt.Println("兔子跑步结束")
}
type Turtle struct {
}
func (t Turtle) Start() {
fmt.Println("乌龟跑步开始")
}
func (t Turtle) End() {
fmt.Println("乌龟跑步结束")
}
type Competition struct {
}
func (c Competition) Running(run Run) {
run.Start()
run.End()
}
func main() {
competition1 := Competition{}
rabbit1 := Rabbit{}
turtle1 := Turtle{}
competition1.Running(rabbit1)
fmt.Println("-----------------------")
competition1.Running(turtle1)
}
小结说明:
1、接口里的所有方法都没有方法体,即接口的方法都是没有实现的方法。接口体现了程序设计的多态和高内聚低偶合的思想。
2、Golang中的接口,不需要显式的实现。只要一个变量含有接口类型中的所有方法,那么这个变量就实现了这个接口。因此,Golang中没有implement这样的关键字 。
注意事项:
1、接口本身不能创建实例但是可以指向一个实现了该接口的自定义类型的变量(实例)
package main
import "fmt"
//一只鸭子有腿、有翅膀、会嘎嘎叫
type Duck interface {
Leg()
Wing()
Gaga()
}
type Goose struct{}
func (g Goose) Leg() {
fmt.Println("有腿")
}
func (g Goose) Wing() {
fmt.Println("有翅膀")
}
func (g Goose) Gaga() {
fmt.Println("会嘎嘎叫")
}
func main() {
var goose Goose
var duck Duck = goose
duck.Gaga()
}
2、接口中所有的方法都没有方法体,即都是没有实现的方法 。
如果加了方法体会直接报错。
3、在 Golang 中,一个自定义类型如果将某个接口的所有方法都实现,我们说这个自定义类型实现了该接口。
如下示例,定义了一个鸭子的接口,鸭子有腿有翅膀会嘎嘎叫。
所以只要一只鸟它有腿有翅膀会嘎嘎叫,那它就是鸭子。
package main
import "fmt"
//一只鸭子有腿、有翅膀、会嘎嘎叫
type Duck interface{
Leg()
Wing()
Gaga()
}
type Goose struct{}
func (g Goose) Leg(){
fmt.Println("有腿")
}
func (g Goose) Wing(){
fmt.Println("有翅膀")
}
func (g Goose) Gaga(){
fmt.Println("会嘎嘎叫")
}
type Birds struct{}
//判断一只鸟是不是鸭子,只要有腿有翅膀会嘎嘎叫就是鸭子
func (b Birds)checkDuck(duck Duck){
duck.Leg()
duck.Wing()
duck.Gaga()
fmt.Println("是鸭子")
}
func main(){
brids := Birds{}
goose := Goose{}
brids.checkDuck(goose)
}
4、只要是自定义数据类型,就可以实现接口,不仅仅是结构体类型
package main
import "fmt"
type B interface {
Test()
}
type integer int
func (i integer) Test() {
fmt.Println("integer Test() i = ",i)
}
func main() {
var i integer = 10
var b B = i
b.Test()
}
5、一个自定义类型可以实现多个接口
package main
import "fmt"
type A interface {
TestA()
}
type B interface {
TestB()
}
type Student struct{}
func (s Student) TestA() {
fmt.Println("Student TestA()")
}
func (s Student) TestB() {
fmt.Println("Student TestB()~~~~~~~~")
}
func main() {
var stu Student
var a A = stu
var b B = stu
a.TestA()
b.TestB()
}
6、Golang 接口中不能有任何变量,否则直接报错
7、一个接口(比如A接口)可以继承多个别的接口(比如B,C接口),这时如果要实现A接口,也必须将B,C接口的方法也全部实现。
如下所示:这时Student结构体同时实现了A、B、C三个接口
package main
import "fmt"
type A interface {
B
C
TestA()
}
type B interface {
TestB()
}
type C interface {
TestC()
}
type Student struct{}
func (s Student) TestA() {
fmt.Println("Student TestA()")
}
func (s Student) TestB() {
fmt.Println("Student TestB()~~~~~~~~")
}
func (s Student) TestC() {
fmt.Println("Student TestC().....")
}
func main() {
var stu Student
var a A = stu
var b B = stu
a.TestA()
a.TestB()
a.TestC()
b.TestB()
}
8、interface类型默认是一个指针(引用类型),如果没有对interface初始化就使用,那么会输出nil
9、空接口 interface() 没有任何方法,所以所有类型都实现了空接口,即我们可以把任何一个变量赋给空接口。
package main
import "fmt"
type A interface {
}
type Student struct{}
func (s Student) TestA() {
fmt.Println("Student TestA()")
}
func main() {
var stu Student
var a A = stu
fmt.Println(a)
var interface2 interface{}
var num1 float64 = 1.01
interface2 = num1
fmt.Println(interface2)
interface2 = "hello"
fmt.Println(interface2)
}