上一章:Chapter012 golang面向对象编程应用思想
下一章:Chapter013 golang文件、命令行参数以及Json
一、基本介绍
interface(接口类型)可以定义一组方法,但是这些不需要实现 。并且 interface不能包含任何变量 ,到某个自定义类型(比如结构体),要使用的时候,再根据具体情况把这些方法写出来(实现接口————》实现接口 所有 方法)
快速入门:
package main
import (
"fmt"
_ "fmt"
)
type Usb interface {
Start()
Stop()
}
type Phone struct {
}
func (p Phone) Start() {
fmt.Printf("手机开始工作\n")
}
func (p Phone) Stop() {
fmt.Printf("手机停止工作\n")
}
type Camera struct {
}
func (c Camera) Start() {
fmt.Printf("相机开始工作\n")
}
func (c Camera) Stop() {
fmt.Printf("相机停止工作\n")
}
type Computer struct {
}
func (c Computer) Working(usb Usb) {
usb.Start()
usb.Stop()
}
func main() {
computer := Computer{}
phone := Phone{}
camera := Camera{}
computer.Working(phone)
computer.Working(camera)
}
运行结果:
二、基本语法
type 接口名 interface{
method1(参数列表) 返回值列表
method2(参数列表) 返回值列表
}
//实现接口:————》实现接口**所有**方法
func (t 自定义类型)method1(参数列表)返回值列表{
//方法实现
}
func (t 自定义类型)method2(参数列表)返回值列表{
//方法实现
}
小结说明:
(1)接口里所有方法都设有方法体,即接口的方法都是没有实现的方法,接口体现了程序设计的 多态和高内聚低耦合 的思想
(2)golang中的接口不需要显示的说明。只要一个变量,含有接口类型中的所有方法,那么这个变量就实现这个接口。因此Golang中 没有implement 这样的关键字。
三、接口的应用场景
1、案例:例如制造轰炸机、武装直升机,专家只需要把飞机需要的功能/规格定下来即可,然后让别人去实现就可以了。
2、项目的规范化开发、控制管理软件开发
四、接口的注意事项和细节
1、接口本身不能创建实例,但是可以指向一个实现了该接口的自定义类型的变量(实例)
package main
import (
"fmt"
_ "fmt"
)
type AInterface interface {
Say()
}
type Stu struct {
Name string
}
func (stu Stu) Say() {
fmt.Printf("Stu Say()")
}
func main() {
var stu Stu
var a AInterface = stu
a.Say()
}
2、接口中所有的方法都设有方法体,即使没有实现的方法
3、在Golang中,一个自定义类型需要将某个接口的所有方法都实现,我们说这个自定义类型实现了该接口
4、只要是 自定义数据类型 ,就可以实现接口,不仅仅是结构体类型
package main
import (
"fmt"
_ "fmt"
)
type AInterface interface {
Say()
}
type integer int
func (i integer) Say(){
fmt.Println("integer Say i")
}
func main(){
var i integer = 10
var b AInterface = i
b.Say() //integer Say i 10
}
5、一个自定义类型可以实现多个接口
package main
import (
"fmt"
_ "fmt"
)
type AInterface interface {
Say()
}
type BInterface interface {
Hello()
}
type Monster struct {
}
func (m Monster) Hello() {
fmt.Print("Monster Hello")
}
func (m Monster) Say() {
fmt.Print("Monster Say")
}
func main() {
//Monster实现了Ainterface和Binterface
var monster Monster
var a2 AInterface = monster
var b2 BInterface = monster
a2.Say()
b2.Hello()
}
6、Golang接口中不能有任何变量
7、一个接口(比如A接口)可以 继承 多个别的接口(比如B、C接口),这时如果要实现A接口,也必须将B、C接口的方法也全部实现
package main
import (
"fmt"
_ "fmt"
)
type Stu struct {
Name string
}
type CInterface interface {
test01()
}
type DInterface interface {
test02()
}
func (stu Stu) test01() {
fmt.Print("test01()\n")
}
func (stu Stu) test02() {
fmt.Print("test02()\n")
}
func (stu Stu) test03() {
fmt.Print("test03()\n")
}
type EInterface interface {
CInterface //继承
DInterface //继承
test03()
}
//如果实现E,就要实现CD和E自己的test03
func main() {
var stu2 Stu
var e EInterface = stu2
e.test01()
e.test02()
e.test03()
}
运行结果:
8、interface 类型默认是一个指针(引用类型),如果没有对 interface 初始化就是要那么会输出nil
9、空接口 interface{} 没有任何方法,所以所有类型都实现了空接口,即:可以把任何一个变量赋给空接口
package main
import (
"fmt"
_ "fmt"
)
type Stu struct {
Name string
}
type T interface{
}
func main(){
var stu Stu
var t T = stu
var t2 interface{} = stu
var num1 float64 = 8.8
t2 = num1
}
五、接口的最佳实践
1、实现对Hero结构体切片的排序
sort.go 官方源码
sort.Sort(data Interface)
所以要实现其len(),less(),swap()三个方法
package main
import (
"fmt"
_ "fmt"
"math/rand"
"sort"
)
//1、声明Hero结构体
type Hero struct {
Name string
Age int
}
//2、声明一个Hero结构体切片类型
type HeroSlice []Hero
//3、实现Interface接口
func (hs HeroSlice) Len() int {
return len(hs)
}
//Less()方法就是决定使用什么标准进行排序
//按照Hero年龄升序排序
func (hs HeroSlice) Less(i,j int) bool {
return hs[i].Age < hs[j].Age
}
func (hs HeroSlice) Swap(i,j int) {
temp :=hs[i]
hs[i] = hs[j]
hs[j] = temp
//下面一句话等价于上面三句话
//hs[i], hs[j] = hs[j], hs[i]
}
func main() {
var heroes HeroSlice
for i:=0;i <10;i++{
hero :=Hero{
Name: fmt.Sprintf("英雄%d", rand.Intn(100)),
Age: rand.Intn(100),
}
heroes = append(heroes,hero)
}
//查看
for _, v := range heroes{
fmt.Print("v=",v,"\n")
}
sort.Sort(heroes)
fmt.Print("排序后:\n")
//查看
for _, v := range heroes{
fmt.Print("v=",v,"\n")
}
}
运行结果:
当然也可以对其他进行排序
所以代码通过接口而变得高效